justik justik - 1 year ago 104
C++ Question

C++ , how to return a reference to the member variable from iterator

There is the following class B derived from std::vector

class B: public std::vector <unsigned int>
B() : std::vector <unsigned int> ( 0 ) {}

and a class A witten as follows:

class A
B b;
double x;

B & getB () {return b;}
B const & getB() const {return b;}

bool operator() ( const A & a ) const
return a < a.x;

Why it is impossible to return a refererence to the variable b of some object A stored in std::list from its iterator (and how to do that)?

int main ()
std::set <A > alist;
std::set <A> ::iterator i_alist = alist.begin();

for (; i_alist != alist.end(); i_list++)
B &il = (*i_alist).getB(); //Compiler error
B &il2 = i_alist->getB(); //Compiler error

il.push_back(10); //Modify il and concurrently B

Compiler error:

Error 1 error C2440: 'initializing' : cannot convert from 'const B' to 'B &' d:\test.cpp

Thanks for your help...

Edit question:

The possible solution using const_cast :

B &il2 = const_cast <B&> ( i_alist->getB() );

Answer Source

This has very little to do with std::vector and everything to do with std::set. You store your objects in a std::set. Elements of std::set are not modifiable from the outside. Once you inserted an element into a set, you cannot change it.

For this reason, std::set::iterator might (and will) evaluate to a constant object, even if it is not a const_iterator (the language specification actually allows std::set::iterator and std::set::const_iterator to refer to the same type, but does not require it). I.e. in your example *i_list is a const-qualified object of type const A. The compiler will call the const version of getB, which returns const B &. You are apparently hoping to break through that constness, expecting the non-const version of getB to be called.

There's no way around it, unless you decide to use some sort of hack (const_cast etc.) to remove the constness from the set element and thus make the compiler to call non-const version of getB.

The const_cast-based hack-solution would look as

B &il = const_cast<A &>(*i_alist).getB();

or you can remove the constness later, from the returned B reference

B &il = const_cast<B &>((*i_alist).getB());
B &il2 = const_cast<B &>(i_alist->getB());
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download