2

I'm having a hard time figuring out how to return a non-const reference to an element in a std::vector from a const class method. A simple example of what I'm going for is,

template<class T>
class MyClass
{
 public:
 MyClass : myVec(3)
 {
 }

 T& x() const
 {
    return *(myVec.data())[0]
 }

 std::vector<T> myVec;
}

The behavior I'm going for is that I'd like to be able to do things like the following,

MyClass obj<double>;
obj.x() = 3.3;
assert(obj.x()==3.3)

Eigen gives the same type of behavior, but I've not been able to figure out how to get it to work.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
jlack
  • 305
  • 2
  • 13
  • @jlack It is not clear why you are trying to return a non-constant reference to a constant object. – Vlad from Moscow Aug 05 '16 at 13:26
  • 1
    Why is `x` const? If you have a mutating accessor it should not be const. – NathanOliver Aug 05 '16 at 13:26
  • It is debatable whether the items within a container should be constant just because the container is. If I have a constant container of non constant pointers, is that fundamentally different? You could view the const-ness as only applying to what items are present, and not what their value is. – nate Aug 05 '16 at 14:29

2 Answers2

11

You could use const_cast, and it'll do the work here, (according to the usage posted). But you won't need it for this case (and for most cases).

You could (and should) add non-const member function overloading for it. Then const member function returns reference to const, non-const member function returns reference to non-const. The appropriate one will be invoked via overload resolution.

const T& x() const
{
   return myVec[0];
}
T& x()
{
   return myVec[0];
}
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
2

Standard library containers extend the const-ness of the container to the values themselves. Since your class is constant in x(), so is the vector. You could use const_cast to remove the const from the item in your accessor.

return const_cast <T&> (*(myVec.data())[0]);

In general this is considered bad practice, since const is there to protect you. Bypassing those protections can make the code harder to reason about.

nate
  • 1,771
  • 12
  • 17