2017-02-16 42 views
2

Я считаю себя достаточно осведомленным относительно более основных аспектов C++, но иногда я склонен запутываться. Я пытаюсь реализовать пару функций, которые действуют на экземпляры std::vector и выполняют некоторые операции со своими значениями, не меняя их на месте. Естественно, я думал, что пройти мимо const& было бы разумным делом. Однако следующий MWE не удается скомпилировать, и я хотел бы понять, почему:const аргументы ссылки на константу в C++

#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; 
} 

Сообщение об ошибке выглядит примерно так:

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 

Я смущен тем, что сообщение об ошибке утверждает, что что-то не может быть перегружено, ссылаясь на звонок func1 внутри func2. Кажется, что есть проблема с разрешением ссылки на векторную запись, но я действительно не понимаю, почему этот фрагмент кода не компилируется. Я рад за любое объяснение, предложение или указатель на документацию об этом типе поведения.

ответ

2
std::vector<const char* const> 

Вы пытаетесь создать экземпляр вектора с типом const. Тип должен быть не менее подвижный, и это не так. Изменить на:

std::vector<const char*> 

вместо

+0

@ nwp: Да, я имел в виду перенос. –

+0

Спасибо за предложение. К сожалению, это действительно не решает проблему, потому что ошибка в 'func2' по-прежнему сохраняется. Мне нужно удалить 'const' также из внутреннего вектора в заголовке' func2' для его успешного компиляции. – carsten

+0

Ну да. Я имел в виду «где-нибудь у вас есть вектор« char const * const »изменить его». –

3

Доклады компилятора свою проблему правильно, если вы просто знаете заранее, что это значит.

std::allocator имеет две перегрузки для address.

address(reference __x) 
address(const_reference __x) 

Проблема для компилятора является то, что для типа шаблона const T, два типа T& и const T& будет иметь тот же тип. И тогда он считает, что есть две копии одной и той же перегрузки.

+0

Хорошо, это имеет смысл. Но как я избегаю этой проблемы? – carsten

+0

Ах, ха! Поэтому, если вы создаете свой собственный распределитель, который имеет только одну из перегрузок, вы можете использовать это как распределитель для своего вектора, и все будет работать плавно! –

+0

@ carsten: Просто используйте неконстантный тип в векторе: 'char const *', а не 'char const * const'. –