Vector of Const Objects Giving Compile Error

Vector of const objects giving compile error

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.

std::vector of objects and const-correctness

I'm not sure why nobody said it, but the correct answer is to drop the const, or store A*'s in the vector (using the appropriate smart pointer).

You can give your class terrible semantics by having "copy" invoke UB or doing nothing (and therefore not being a copy), but why all this trouble dancing around UB and bad code? What do you get by making that const? (Hint: Nothing.) Your problem is conceptual: If a class has a const member, the class is const. Objects that are const, fundamentally, cannot be assigned.

Just make it a non-const private, and expose its value immutably. To users, this is equivalent, const-wise. It allows the implicitly generated functions to work just fine.

Errors declaring static const vector in .h file and errors in definitions in .cpp file

You don't need the (13) after the declarations/definitions of your two std::vector objects; in fact, you cannot have them. In the header, you only need to declare the vectors; in your source file, the initializer lists will tell the compiler what those vectors should contain.

Explanation: Although you can have a statement like const std::vector<int> dinMon(13) as "free-standing" code (it will construct the said vector with 13 elements), you cannot do this in the declaration of a static class member: this is, after all, only a declaration. So, just the plain vector type - and then the definition (in Data.cpp) has to match, so you can't have the (13) there, either.

Also, you are missing a ; after the declaration of your Date class (that is, after the closing curly brace in your header file).

Date.h:

class Date {
private:
int month;
int day;
int year;
static const std::vector<std::string> monthNames;
static const std::vector<int> daysInMonths;
public:
Date();
Date(int month, int day, int year);
}; // You forgot the semicolon here!

Date.cpp:

#include "Date.h"
// #include <vector> // Don't need to re-include these, as they are already ...
// #include <string> // ... included by "Date.h"
const std::vector<std::string> Date::monthNames {
"", "January", "February", "March", "April", "May",
"June", "July", "August", "September", "October", "November", "December"
};
const std::vector<int> Date::daysInMonths { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

Date::Date() : month(1), day(1), year(1900) {
}

Date::Date(int month, int day, int year) : month(month), day(day), year(year) {
}

Why does const vector const pair ... give an 'cannot be overloaded' error?

This is what I could gather so far from the standard and documentation:

std::vector is an allocator-aware container.

As per C++17 (final working draft N4659)

20.5.3.5 Allocator requirements [allocator.requirements]

Table 30 says:

T, U, C any cv-unqualified object type (6.9)

For std::vector it is also required that element type is a complete type and meets the requirements of Erasable.

From [container.requirements.general]/15 we have:

Given an allocator type A and given a container type X having a
value_type identical to T and an allocator_- type identical to
allocator_traits<A>::rebind_alloc<T> and given an lvalue m of type A,
a pointer p of type T*, an expression v of type (possibly const) T,
and an rvalue rv of type T, the following terms are defined.

...

(15.6) — T is Erasable from X means that the following expression is
well-formed: allocator_traits<A>::destroy(m, p)

Since element type in the question is const qualified, it fails to meet the requirements.

Copy constructor error when initilizing a vector of custormer typed objects

Look at the signature of the invoked constructor of std::vector:

vector(size_type n, const T& value, const Allocator& = Allocator());

The argument f is passed by const reference (parameter value). That parameter therefore cannot be bound to non-const parameter foo of type Foo& of Foo's copy constructor.


Same (simpler) case:

Foo f;
const Foo& value = f;
Foo& foo = value; // error

const vector implies const elements?

The first version

v[0].set (1234); 

does not compile because it tries to change the vector's first element returned to it by reference. The compiler thinks it's a change because set(int) is not marked const.

The second version, on the other hand, only reads from the vector

(*v[0]).set(1234);

and calls set on the result of the dereference of a constant reference to a pointer that it gets back.

When you call v[0] on a const vector, you get back a const reference to A. When element type is a pointer, calling set on it is OK. You could change the second example to

v[0]->set(1234);

and get the same result as before. This is because you get a reference to a pointer that is constant, but the item pointed to by that pointer is not constant.

Reference to container of const in function signature

The answer is in the comment sections: "The type of a vector has to be copy assignable until C++11 and const is not assignable".



Related Topics



Leave a reply



Submit