2010-01-10 22 views
7

Gần đây tôi đã gặp phải sự cố kỳ lạ khi tôi nhận được const_iterator thay vì số iterator được mong đợi khi lặp qua nhiều lần. Hóa ra là một vấn đề không cho MSVC nhưng g ++ đã cho tôi một lỗi:C++ Tiêu chuẩn: Trình cố định không mong đợi trong multiset

error: invalid initialization of reference of type 'myPtr&' from expression of type 'const boost::shared_ptr'

đang liên quan:

typedef std::multiset<myPtr> myList; 
myList _mystuff; 
void tick(float dt) 
{ 
    for (myList::iterator i = _mystuff.begin(); i != _mystuff.end(); ++i) 
    { 
     myPtr &mine = *i; // g++ problem here, not for MSVC 
     // const myPtr &mine = *i; works fine for g++ 
     mine->tick(dt); 
    } 
} 

Khá một chút nghiên cứu tiết lộ rằng là một vấn đề với rất nhiều cuộc thảo luận trước đó . Tôi tìm thấy những bit có liên quan:

kiến ​​thức cơ bản của tôi và nắm bắt về vấn đề này còn hạn chế và do đó tôi muốn muốn biết liệu tiêu chuẩn không định nghĩa điều này hành vi đủ tốt trong trường hợp g ++ và MSVC thực hiện hành vi theo ý thích của chúng hoặc cho dù g ++ hoặc MSVC đi chệch khỏi một tiêu chuẩn được xác định rõ.

Xin cảm ơn trước.

+0

thay đổi các decl của 'tôi' cho 'const myPtr & mine'. Tất nhiên, 'tick' sẽ phải được khai báo 'void tick (float) const;' và bất kỳ thành viên dữ liệu nào được sửa đổi bằng tick sẽ cần phải là 'mutable'. – KitsuneYMG

Trả lời

15

Các trình vòng lặp cho tập hợp và nhiều bộ được thay đổi từ cặp lặp iterator/const chuẩn để chỉ là các trình vòng lặp const. Lý do cho sự thay đổi này là chúng được đặt hàng container, và thay đổi các yếu tố bên trong của một iterator thực sự có thể làm mất hiệu lực ràng buộc đặt hàng này.

Phiên bản GCC mà bạn đang thử nghiệm đã thực hiện thay đổi này, phiên bản VC mà bạn đang sử dụng không có. VC10 (và VC9 SP1, tôi tin) luôn luôn trả về const_iterators từ bộ và multisets.

23.2.4/6 của dự thảo mới nhất của C++ 1x (n3000.pdf vào lúc này) nói

For associative containers where the value type is the same as the key type, both iterator and const_iterator are constant iterators.

std :: set và std :: multi_set là container kết hợp giá trị loại là giống như loại khóa.

+0

Tuyệt vời! Tôi chỉ cần thử nghiệm VC10b2 và thực sự tôi đã nhận lỗi tương tự.Bây giờ nếu tôi chỉ hiểu phần nào của tiêu chuẩn đã xác định chính xác điều này. – Svenstaro

+0

23.2.4/6 của bản nháp mới nhất của C++ 1x cho biết "Đối với các thùng chứa liên kết trong đó loại giá trị giống với loại khóa, cả trình lặp và hằng số là các trình lặp không đổi." std :: set and std :: multi_set là các thùng chứa kết hợp, trong đó kiểu giá trị giống với kiểu khóa. –

1

Làm thế nào để đánh lừa trình biên dịch cho std :: set :: iterator?

Tôi đã struct

struct _item { 
    int a; 
    int b; 
    bool operator <(const _item& x) const {return a<x.a;} 
}; 

Tôi muốn thay đổi chỉ thành viên b (b là không thích hợp để phân loại trong tập, chỉ có thành viên một được so sánh).

std::set<_item> data; 
std::set<_item>::iterator iter=data.begin(); 
iter->b=0; // error !!! 

Avada Kedavra!

struct _item { 
    int a; 
    int b; 
    _item* self; 
    _item() {self=this;} 
    bool operator <(const _item& x) const {return a<x.a;} 
}; 
iter->self->b=0; // Success !! Tested on VC10 

Dĩ nhiên hơn C + + đúng

struct _item { 
    int a; 
    int b; 
private: 
    _item* self; 
public: 
    _item() {self=this;} 
    bool operator <(const _item& x) const {return a<x.a;} 
    int& bReference() const {return self->b;} 
}; 
std::set<_item> items; 
std::set<_item>::iterator iter=items.begin(); 
iter->bReference()=0; // Success !! Tested on VC1 
+1

anh ta muốn thông tin abt tiêu chuẩn và không phải là một workaround – owagh

+0

Hoặc bạn có thể sử dụng 'const_cast'. Bằng cách này, giải pháp của bạn không thành công nếu phần tử được sao chép hoặc gán. – immibis

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