Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vector of const objects giving compile error

I have declared the following in my code

vector <const A> mylist;  

I get the following compile error -

new_allocator.h:75: error: `const _Tp* __gnu_cxx::new_allocator<_Tp>::address(const _Tp&) const \[with _Tp = const A]' and `_Tp* __gnu_cxx::new_allocator<_Tp>::address(_Tp&) const [with _Tp = const A]' cannot be overloaded 

But if declare -

vector <A> mylist; 

my code compiles.

Is const not allowed in this context?

I am copying my code here for everyone'e reference -

#include <iostream> #include <vector>  using namespace std; class A { public:     A () {cout << "default constructor\n";}     A (int i): m(i) {cout << "non-default constructor\n";}  private:     int m; };  int main (void) {     vector<const A> mylist;      mylist.push_back(1);      return 0; } 
like image 465
Satabdi Avatar asked Jun 26 '13 06:06

Satabdi


People also ask

What is a const vector?

A const vector will return a const reference to its elements via the [] operator . In the first case, you cannot change the value of a const int&. In the second case, you cannot change the value of a reference to a constant pointer, but you can change the value the pointer is pointed to.

Can we change a const vector C++?

const vector<string>: Cannot change anything about the vector.

Can you push const vector back?

You can't put items into a const vector, the vectors state is the items it holds, and adding items to the vector modifies that state.

Can you sort a const vector?

Yes, you can sort a const vector in C++.


2 Answers

Items in a vector must be assignable (or, in more recent versions of the standard, movable). const objects aren't assignable, so attempting to store them in a vector will fail (or at least can fail -- the code is invalid, but a compiler is free to accept it anyway, if it so chooses, though most programmers would generally prefer that invalid code be rejected).

I suppose for the truly pedantic, if you wanted to badly enough, you could define a type that was assignable despite being const, something like this:

class ugly {      mutable int x; public:     ugly const &operator=(ugly const &u) const {          x = u.x;         return *this;     } }; 

I believe you should be able to store items of this type in a vector even though they're const. A quick test of creating a vector of these succeeds with VC++. This failed with some older compilers (e.g., failed with g++ 4.8.1), but works with reasonably recent ones (VC++ back to at least 2015, g++ back to at least 5.4 and clang++ back to at least 4.0--though I haven't tried to track down the first version of each that supported it).

For a current compiler, a type that supported moving const objects would probably work just as well. But, just in case it wasn't obvious: this is allowing you to modify an object even though it's marked const. That's clearly a direct violation of any reasonable user's expectations, so it's mostly a problem, not a solution.

like image 142
Jerry Coffin Avatar answered Sep 19 '22 14:09

Jerry Coffin


The use of the push_back method is the problem. emplace_back will compile. Another alternative (depending on the whole situation you do not describe here) would be to use a vector<A const&> if the inserted items have a life outside the vector. Items in a vector do not need to be assignable, but when they are not, some member functions and algorithms can not be used.

Explanation :

push_back is supposed to first default-construct an A in the vector, then assign (using copy-construct) the given reference. This breaks your const qualification, hence does not compile.

emplace_back uses "perfect forwarding" to invoke the actual constructor directly in place.

like image 23
lip Avatar answered Sep 18 '22 14:09

lip