I'm trying to define a constant list of constant objects and I can't seem to get it done. Here is my example that compiles fine:
#include <string>
#include <list>
class Person { public:
std::string name;
Person(const std::string &in_name){name=in_name;}
};
class MyClass { public:
const std::list</* const */Person> l;
MyClass(const std::list</* const */Person> &in_l):l(in_l){}
};
int main(int argc, char **argv) {
Person dave("dave");
MyClass c(std::list<const Person>(dave));
return 0;
}
When I remove the comments from const
in those 2 places,
I get the following errors:
In file included from /usr/include/x86_64-linux-gnu/c++/7/bits/c++allocator.h:33:0,
from /usr/include/c++/7/bits/allocator.h:46,
from /usr/include/c++/7/string:41,
from main66.cpp:1:
/usr/include/c++/7/ext/new_allocator.h: In instantiation of ‘class __gnu_cxx::new_allocator<const Person>’:
/usr/include/c++/7/bits/allocator.h:108:11: required from ‘class std::allocator<const Person>’
main66.cpp:11:53: required from here
/usr/include/c++/7/ext/new_allocator.h:93:7: error: ‘const _Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::const_reference) const [with _Tp = const Person; __gnu_cxx::new_allocator<_Tp>::const_pointer = const Person*; __gnu_cxx::new_allocator<_Tp>::const_reference = const Person&]’ cannot be overloaded
address(const_reference __x) const _GLIBCXX_NOEXCEPT
^~~~~~~
/usr/include/c++/7/ext/new_allocator.h:89:7: error: with ‘_Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::reference) const [with _Tp = const Person; __gnu_cxx::new_allocator<_Tp>::pointer = const Person*; __gnu_cxx::new_allocator<_Tp>::reference = const Person&]’
address(reference __x) const _GLIBCXX_NOEXCEPT
^~~~~~~
Is there any way to define a std::list of const objects?
Allocator-aware containers, such as std::list
, cannot take const
value types, because the Allocator requirements specify behavior only for cv-unqualified types. This means that the container is not guaranteed to be able to create the element objects through the allocator interface if the value type is const
or volatile
qualified.
This is not a problem though, because the container being const
is enough to guarantee that the elements are not changed. If you access an element of the container through a const
reference to the container, you will only ever get a const
reference to the element.
So, just use const std::list<Person>
, instead of const std::list<const Person>
.
Technically someone could const_cast
the const
ness away from such a reference to be able to modify the elements and that would probably be legal, i.e. not undefined behavior, but that is something that a user can always do, just that it would cause undefined behavior with const
objects.
See also Does C++11 allow vector<const T>? for details.