Iterators STL and 'const'

I have a problem with what seems to be some kind of implicit casting for const when I use iterators. I'm not sure which code matters (if I did, I probably would not ask this question!), So I will try my best to illustrate my problem.

typedef set<SmallObject> Container; //not const void LargeObject::someFunction() { //not const Container::iterator it; //not const for (it = c.begin(); it != c.end(); ++it) { //assume c is a "Container" (*it).smallObjectFunction(); //not a const function } } 

However, I always get the following error:

 error: passing 'const SmallObject' as 'this' argument of 'int SmallObject::smallObjectFunction()' discards qualifiers 

However, if I pass it as ((SmallObject)(*it).smallObjectFunction(); then I will get rid of the error message.

The only thing I can understand is that somehow the definition

 bool operator< (const SmallObject &a) const; 

somehow forces the iterator to return const objects. Any help or explanation here?

+4
source share
3 answers

Settings and maps keep items in order according to the sorting condition. In order for the user code not to interrupt the invariants, the key cards and the entire element in the set must be constant. Your problem is that the saved item is not a SmallObject , but a const SmallObject .

If this was not limited, you could:

 int init[] = { 1, 2, 3, 4, 5 }; std::set<int> values( init, init+5 ); std::copy( values.begin(), values.end(), std::ostream_iterator<int>(std::cout, " ")); // 1 2 3 4 5 *(values.find(3)) = 5; // luckily this does not work! std::copy( values.begin(), values.end(), std::ostream_iterator<int>(std::cout, " ")); // 1 2 5 4 5 -- not in order!!! 

The problem is not only that now the set element would not be in order, but depending on how the tree was built, there may be elements that are present in the set but cannot be found.

+11
source

Your code is not stupid and can compile using the appropriate STL implementation, depending on some of the design decisions that your STL implementation has implemented. The C ++ 03 standard does not specify what should be a reference typedef for set :: iterators (in my opinion, they should be mutable references). So keep doing what you are doing, but insert const_cast :

 const_cast<SmallObject&>(*it).smallObjectFunction(); 

It is more efficient and much clearer than erasing and reinstalling. For a more detailed discussion of this issue, see paragraph 8 in the "More Exceptional C ++" section of Herb Sutter.

It is safe to do const_cast in this situation, and this is not a bad style, just make sure that you do not change the value of the fields that determine the order. If the class interface makes it difficult to verify that you are not changing the order, then the interface is probably not very well designed.

+3
source

The object (s) in your container c are const, and the smallObjectFunction function tries to change the value of the object.

0
source

All Articles