2011-01-24 25 views
12

Tôi có một chức năng với một chữ kýC++ Làm thế nào để vượt qua một danh sách các phi consts đến một chức năng muốn một danh sách các consts

void Foo(list<const A*>) 

và tôi muốn vượt qua nó một

list<A*> 

Làm thế nào để tôi làm điều này? (ghi chú plz - danh sách không phải là hằng số, chỉ thành viên của danh sách)

+0

Bạn đã thử chuyển danh sách giống như nó chưa? Nếu vậy, bạn đã nhận được gì? – Oswald

+0

@Oswald, một số lỗi đúc mẫu khủng khiếp – vondip

+0

Thứ gì đó như 'lỗi: chuyển đổi từ 'std :: danh sách >' thành loại vô hướng 'std :: list > 'yêu cầu'? – James

Trả lời

19

Vấn đề bạn có là mặc dù T * có thể được ngầm chuyển đổi sang một T const *, hệ thống mẫu không phải là "nhận thức" đó, do đó, một whatever<T *>whatever<T const *> là loại hoàn toàn không liên quan, và không có chuyển đổi ngầm từ một đến người khác.

Để tránh sự cố, tôi có thể tránh phải vượt qua bộ sưu tập. Thay vào đó, tôi sẽ có chức năng lấy một cặp lặp. A list<A *>::iteratorcó thể được chuyển đổi hoàn toàn thành list<A *>::const_iterator. Cho rằng vấn đề, tôi có thể làm cho các chức năng một mẫu, vì vậy nó có thể mất vòng lặp của loại tùy ý.

Điều này có thể giúp bạn tiết kiệm khá nhiều rắc rối - một list là hiếm khi một lựa chọn tốt của container, vì vậy có một cơ hội rất lớn mà một ngày nào đó bạn sẽ muốn thay đổi từ list<A *> để vector<A *> hoặc có lẽ deque<A *> - - và nếu bạn thực hiện chức năng chung của mình, bạn sẽ có thể làm điều đó mà không cần viết lại hàm nào cả.

+7

Lời khuyên tốt về việc sử dụng trình lặp. Tuy nhiên, không có mối quan hệ nào giữa 'danh sách :: iterator' và' danh sách :: iterator' (hoặc 'const_iterator'), do đó, một hàm lấy các trình vòng lặp phải lấy chúng làm tham số mẫu. –

+1

@Oswald: có lẽ một 'reinterpret_cast' sẽ hoạt động trong trường hợp rất đặc biệt này. Tuy nhiên không có giải pháp sạch trừ việc trừu tượng hóa danh sách qua các trình vòng lặp. Trong C# 4 bạn có generics biến đổi, mà giải quyết các loại vấn đề khá thanh lịch (và mở cửa cho abstractions mạnh mẽ). –

0

Bạn chỉ có thể tạo danh sách mới và điền danh sách đó với các giá trị từ danh sách gốc của bạn. Có lẽ không phải là giải pháp hiệu quả nhất như xa như thời gian chạy và quản lý bộ nhớ là có liên quan, nhưng chắc chắn dễ dàng để mã:

list<A*> list1; 
list<const A*> list2; 
for(list<A*>::iterator a=list1.begin(); a!=list1.end(); a++) list2.push_back(*a); 
0

Bạn sẽ phải tạo một bản sao của danh sách - đó là một pass-by-value tranh luận. Có một cách khá đơn giản để tạo một bản sao, vì các kiểu phần tử có một chuyển đổi ngầm: tất cả các thùng chứa STL có thể được tạo ra từ một cặp các trình lặp. Vì vậy, trong trường hợp của bạn:

std::list<A*> src; 
Foo(std::list<const A*>(src.begin(), src.end())); 

Điều này hơi khó hơn, vì STL đại diện cho các cặp lặp và quy tắc chuyển đổi C++ hoạt động trên các đối tượng đơn lẻ.

Các vấn đề liên quan