justik justik - 27 days ago 16
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>
{
public:
B() : std::vector <unsigned int> ( 0 ) {}
};


and a class A witten as follows:

class A
{
private:
B b;
double x;

public:
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() );

AnT AnT
Answer

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());
Comments