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 lvaluem
of typeA
,
a pointerp
of typeT*
, an expressionv
of type (possibly const)T
,
and an rvaluerv
of typeT
, 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
How to Stop Name-Mangling of My Dll's Exported Function
Static Variables in an Inlined Function
Is Using Double Faster Than Float
How to Define a C++ Preprocessor MACro Through the Command Line with Cmake
Measure Execution Time in C++ Openmp Code
Matching Alias Template as Template Argument
Difference Between Pointer to a Reference and Reference to a Pointer
What Are the Signs of Crosses Initialization
How to Raise Warning If Return Value Is Disregarded
How Does One Securely Clear Std::String
Isdigit(C) - a Char or Int Type
Preparation for Std::Iterator Being Deprecated
What Is the Best Encryption Library in C/C++
Practical Use of Zero-Length Bitfields
How to Use Visual Studio Code to Compile Multi-Cpp File
Are Vectors Passed to Functions by Value or by Reference in C++