haisareisa
haisareisa

Reputation: 33

const_iterator type of a container of const types

If I compile the code below:

#include <list>

using iter_t = std::list<const unsigned>::const_iterator;

int main(int, char**) {
  return 0;
}

I get the following compile error:

In file included from /usr/local/Cellar/gcc/4.9.2_1/include/c++/4.9.2/x86_64-apple-darwin13.4.0/bits/c++allocator.h:33:0,
             from /usr/local/Cellar/gcc/4.9.2_1/include/c++/4.9.2/bits/allocator.h:46,
             from /usr/local/Cellar/gcc/4.9.2_1/include/c++/4.9.2/list:61,
             from main.cpp:1:
/usr/local/Cellar/gcc/4.9.2_1/include/c++/4.9.2/ext/new_allocator.h: In instantiation of 'class __gnu_cxx::new_allocator<const unsigned int>':
/usr/local/Cellar/gcc/4.9.2_1/include/c++/4.9.2/bits/allocator.h:92:11:   required from 'class std::allocator<const unsigned int>'
/usr/local/Cellar/gcc/4.9.2_1/include/c++/4.9.2/bits/stl_list.h:315:9:   required from 'class std::_List_base<const unsigned int, std::allocator<const unsigned int> >'
/usr/local/Cellar/gcc/4.9.2_1/include/c++/4.9.2/bits/stl_list.h:447:11:   required from 'class std::list<const unsigned int>'
main.cpp:3:41:   required from here
/usr/local/Cellar/gcc/4.9.2_1/include/c++/4.9.2/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 unsigned int; __gnu_cxx::new_allocator<_Tp>::const_pointer = const unsigned int*; __gnu_cxx::new_allocator<_Tp>::const_reference = const unsigned int&]' cannot be overloaded
   address(const_reference __x) const _GLIBCXX_NOEXCEPT
   ^
/usr/local/Cellar/gcc/4.9.2_1/include/c++/4.9.2/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 unsigned int; __gnu_cxx::new_allocator<_Tp>::pointer = const unsigned int*; __gnu_cxx::new_allocator<_Tp>::reference = const unsigned int&]'
   address(reference __x) const _GLIBCXX_NOEXCEPT
   ^

I get roughly the same error message if I change the container type from std::list to std::vector, std::deque or std::forward_list. If I change the template argument from const unsigned to unsigned it compiles fine.

What's going on here? I can't see why it wouldn't compile.

Upvotes: 0

Views: 619

Answers (1)

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145279

Visual C++ 2015 gives the clarifying diagnostic

The C++ Standard forbids containers of const elements because allocator<const T> is ill-formed.

As I understand it, this is because an allocator's allocate method returns a pointer to an array of uninitialized T items, and if T is const then these items can never be initialized.

I can't find any explicit statement that allocator<const T> is ill-formed, so it is presumably a consequence of the semantics.

As Dieter Lücking notes in a comment, there is a direct clash for const type T between the two member functions that provide address of a reference and const_reference, because these are equal when the type is const.

Upvotes: 2

Related Questions