4

I saw this answer: Does C++11 allow vector<const T>? explains how you should not use const T in a std::vector. I tried this with std::vector<const int> int_vector and got compiler error, which is expected. But if I create an std::vector<const CustomType*> custom_type_vector I can use it with no problem. Does this mean c++ allows const pointer as an element within a std::vector but does not allow const T in std::vector?

minimal reproducible example

std::vector<const int> vec_a; // compiler will complain this.
std::vector<const int*> vec_a; // compiler will accept this.

The error log for using std::vector<const int> is:

/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 int; __gnu_cxx::new_allocator<_Tp>::const_pointer = const int*; __gnu_cxx::new_allocator<_Tp>::const_reference = const int&]' 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 int; __gnu_cxx::new_allocator<_Tp>::pointer = const int*; __gnu_cxx::new_allocator<_Tp>::reference = const int&]'
       address(reference __x) const _GLIBCXX_NOEXCEPT
       ^~~~~~~
/usr/include/c++/7/ext/new_allocator.h:125:19: error: invalid conversion from 'const void*' to 'void*' [-fpermissive]
  ::operator delete(__p);
  ~~~~~~~~~~~~~~~~~^~~~~

My compiler version is gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)

L. F.
  • 19,445
  • 8
  • 48
  • 82

1 Answers1

10

As m_pOatrix correctly points out in the comments, std::vector<const CustomType*> is not a vector of const pointers, but a vector of pointers to const objects, and this is allowed.

If you instead had const pointers, this would be disallowed:

std::vector<Foo> f; // allowed
std::vector<const Foo> f; // disallowed
std::vector<const Foo*> f;// allowed
std::vector<Foo* const> f; // disallowed

The trick with const is that it applies to the thing immediately to the left of it, or if it's at the beginning (like it often is) then it applies to the first thing.

const Foo*; // pointer to const Foo, same as Foo const*
Foo* const; // const pointer to Foo
Tas
  • 7,023
  • 3
  • 36
  • 51
  • Thanks for the explanation, apparently this question is due to me lacking of knowledge about the syntax/usage of const keyword. It is tricky but it all makes sense now. – PinkFloiiid Nov 23 '19 at 00:39
  • 1
    It would probably more useful to point out that cv-qualifiers go directly behind the type they apply to, but if they are before everything else, as a matter of convenience they are treated as if they were just after the first part. – Deduplicator Nov 23 '19 at 01:49