carsten
carsten

Reputation: 1365

const vector reference arguments in c++

I consider myself fairly knowledgeable regarding the more basic aspects of C++, but sometimes I tend to get confused. I'm trying to implement a pair of functions that act on instances of std::vector and do some operations with their values, without changing them in-place. Naturally, I thought that a pass by const& would be a reasonable thing to do. However, the following MWE fails to compile, and I would like to understand why:

#include<vector>

void func1(const std::vector<const char* const>& v){
     // do stuff
}

void func2(const std::vector<const std::vector<const char* const> >& v){
  for(int i=0;i<v.size();++i){
    func1(v[i]);
  }
}

int main(){
    return 0;
}

The error message looks somewhat like this:

In file included from...include/c++/4.9.3/x86_64-unknown-linux-gnu/bits/c++allocator.h:33:0,
                 from...include/c++/4.9.3/bits/allocator.h:46,
                 from...include/c++/4.9.3/vector:61,
                 from test.cxx:2:
.../ext/new_allocator.h: In instantiation of ‘class __gnu_cxx::new_allocator<const std::vector<const char* const> >’:
.../bits/allocator.h:92:11:   required from ‘class std::allocator<const std::vector<const char* const> >’
.../ext/alloc_traits.h:172:53:   required from ‘struct __gnu_cxx::__alloc_traits<std::allocator<const std::vector<const char* const> > >’
.../bits/stl_vector.h:75:28:   required from ‘struct std::_Vector_base<const std::vector<const char* const>, std::allocator<const std::vector<const char* const> > >’
.../bits/stl_vector.h:214:11:   required from ‘class std::vector<const std::vector<const char* const> >’
test.cxx:9:18:   required from here
.../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::vector<const char* const>; __gnu_cxx::new_allocator<_Tp>::const_pointer = const std::vector<const char* const>*; __gnu_cxx::new_allocator<_Tp>::const_reference = const std::vector<const char* const>&]’ cannot be overloaded
       address(const_reference __x) const _GLIBCXX_NOEXCEPT
       ^
.../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::vector<const char* const>; __gnu_cxx::new_allocator<_Tp>::pointer = const std::vector<const char* const>*; __gnu_cxx::new_allocator<_Tp>::reference = const std::vector<const char* const>&]’
       address(reference __x) const _GLIBCXX_NOEXCEPT
       ^
.../ext/new_allocator.h: In instantiation of ‘class __gnu_cxx::new_allocator<const char* const>’:
.../bits/allocator.h:92:11:   required from ‘class std::allocator<const char* const>’
.../ext/alloc_traits.h:172:53:   required from ‘struct __gnu_cxx::__alloc_traits<std::allocator<const char* const> >’
.../bits/stl_vector.h:75:28:   required from ‘struct std::_Vector_base<const char* const, std::allocator<const char* const> >’
.../bits/stl_vector.h:214:11:   required from ‘class std::vector<const char* const>’
test.cxx:10:14:   required from here
.../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 char* const; __gnu_cxx::new_allocator<_Tp>::const_pointer = const char* const*; __gnu_cxx::new_allocator<_Tp>::const_reference = const char* const&]’ cannot be overloaded
       address(const_reference __x) const _GLIBCXX_NOEXCEPT
       ^
.../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 char* const; __gnu_cxx::new_allocator<_Tp>::pointer = const char* const*; __gnu_cxx::new_allocator<_Tp>::reference = const char* const&]’
       address(reference __x) const _GLIBCXX_NOEXCEPT

I'm confused by the fact that the error message claims that something cannot be overloaded, referring to the call of func1 inside func2. It seems like there's an issue with resolving the const reference to the vector entry, but I really don't understand why this piece of code does not compile. I'm happy for any explanation, suggestion, or pointer to documentation about this type of behavior.

Upvotes: 2

Views: 4957

Answers (2)

Bo Persson
Bo Persson

Reputation: 92311

The compiler reports its problem correctly, if you just know beforehand what that means.

The std::allocator has two overloads for address.

address(reference __x)
address(const_reference __x)

The problem for the compiler is that for a template type const T, the two types T& and const T& will be the same type. And then it believes that there are two copies of the same overload.

Upvotes: 3

std::vector<const char* const>

You are trying to instantiate a vector with a const type. The type needs to be at least moveable, and that isn't. Change to:

std::vector<const char*>

instead

Upvotes: 4

Related Questions