I have this simple code:
#include <vector>
#include <string>
void foo(const std::vector<std::pair<std::string, int> > & networks) {
for (auto p : networks) {
}
}
void bla(const std::vector<const std::pair<std::string, int> > & networks) {
for (auto p : networks) {
}
}
This produces an error in bla()
:
mrvn@frosties:~% g++ -O2 -W -Wall -g -std=gnu++17 -c bla.cc
In file included from /usr/include/x86_64-linux-gnu/c++/5/bits/c++allocator.h:33:0,
from /usr/include/c++/5/bits/allocator.h:46,
from /usr/include/c++/5/vector:61,
from bla.cc:1:
/usr/include/c++/5/ext/new_allocator.h: In instantiation of ‘struct __gnu_cxx::new_allocator<const std::pair<std::__cxx11::basic_string<char>, int> >’:
/usr/include/c++/5/bits/allocator.h:92:11: required from ‘class std::allocator<const std::pair<std::__cxx11::basic_string<char>, int> >’
/usr/include/c++/5/bits/stl_vector.h:79:14: required from ‘struct std::_Vector_base<const std::pair<std::__cxx11::basic_string<char>, int>, std::allocator<const std::pair<std::__cxx11::basic_string<char>, int> > >::_Vector_impl’
/usr/include/c++/5/bits/stl_vector.h:164:20: required from ‘struct std::_Vector_base<const std::pair<std::__cxx11::basic_string<char>, int>, std::allocator<const std::pair<std::__cxx11::basic_string<char>, int> > >’
/usr/include/c++/5/bits/stl_vector.h:214:11: required from ‘class std::vector<const std::pair<std::__cxx11::basic_string<char>, int> >’
bla.cc:10:17: required from here
/usr/include/c++/5/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 std::pair<std::__cxx11::basic_string<char>, int>; __gnu_cxx::new_allocator<_Tp>::const_pointer = const std::pair<std::__cxx11::basic_string<char>, int>*; __gnu_cxx::new_allocator<_Tp>::const_reference = const std::pair<std::__cxx11::basic_string<char>, int>&]’ cannot be overloaded
address(const_reference __x) const _GLIBCXX_NOEXCEPT
^
/usr/include/c++/5/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 std::pair<std::__cxx11::basic_string<char>, int>; __gnu_cxx::new_allocator<_Tp>::pointer = const std::pair<std::__cxx11::basic_string<char>, int>*; __gnu_cxx::new_allocator<_Tp>::reference = const std::pair<std::__cxx11::basic_string<char>, int>&]’
address(reference __x) const _GLIBCXX_NOEXCEPT
^
My Question is: WHY?
Note: used g++ 5.4 and 7.3.
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.
If the vector itself is declared const (as in const std::vector<T*>), then you can't modify the vector, but you can modify the objects. If the pointers are declared const (as in std::vector<const T*>), then you can modify the vector, but not the objects.
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. If you want to append to a vector you must take in a non const ref.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With