With a container class, such as std::vector
, there are two different concepts of constant-ness: that of the container (i.e. its size) and that of the elements. It seems that std::vector
confuses these two, such that the following simple code won't compile:
struct A {
A(size_t n) : X(n) {}
int&x(int i) const { return X[i]; } // error: X[i] is non-const.
private:
std::vector<int> X;
};
Note that even though the data members (the three pointers to the begin&end of the data and the end of the allocated buffer) of std::vector
are not changed by a call to its operator[]
, this member is not const
-- isn't this a strange design?
Note also that for raw pointers, these two concepts of constant-ness are neatly separated, such that the corresponding raw-pointer code
struct B {
B(size_t n) : X(new int[n]) {}
~B() { delete[] X; }
void resize(size_t n); // non-const
int&x(int i) const { return X[i]; } // fine
private:
int*X;
};
works just fine.
So what is the correct/recommended way to deal with this when using std::vector
(without using mutable
)?
Is a const_cast<>
as in
int&A::x(int i) const { return const_cast<std::vector<int>&>(X)[i]; }
deemed acceptable (X
is known to be non-const
, so no UB here)?
EDIT just to prevent further confusion: I do want to modify the elements, i.e. the contents of the container but not the container itself (the size and/or memory location).