2015-04-07 2 views
7

cppreference показывает эту подпись для std::cbegin:Почему станд :: cbegin возвращает тот же тип, как станд :: начинают

template< class C > 
constexpr auto cbegin(const C& c) -> decltype(std::begin(c)); 

Не должна ли она вернуть что-то вроде C::const_iterator вместо этого?

+0

Я согласен с тем, что страница может быть немного понятнее и не позволять людям рассуждать об этом (как это сделано в данных ответах). Кроме того, объяснение, почему введен cbegin (чтобы гарантировать стабильность, а не только полагаться на константу параметра), может помочь. – stefaanv

ответ

12

c является const ссылкой, так std::begin(c) он будет возвращать независимо перегрузку const из C::begin() возвращается. Для стандартных типов библиотек это const_iterator. Для типа массива это указатель на const.

Обратите внимание, что это зависит от другого, нестандартного пользователя библиотеки определенной C, осуществляются здраво с const перегрузкой для C::begin(), который возвращает итератор, который дает вам const доступ к элементам контейнера.

3

std::begin возвращает iterator или const_iterator, в зависимости от того, является ли аргумент const или нет, см., Например, http://en.cppreference.com/w/cpp/iterator/begin и объявление функции члена begin стандартного контейнера http://en.cppreference.com/w/cpp/container/vector/begin

std::cbegin возвращает то, что std::begin возвращается (через decltype), так что если у вас есть const объект, перегрузка const выбран, который в свою очередь возвращает const_iterator.

2

cbegin реализуется, как показано ниже:

template <class C> 
auto cbegin(const C& container)->decltype(std::begin(container)) 
{ 
    return std::begin(container); // see explanation below 
} 

соответствующие начинаются, как показано ниже.

template< class C > 
auto begin(C& c) -> decltype(c.begin()); //calling container's begin 

Этого шаблон cbegin принимает любой тип аргумента , представляющей структуру данных контейнера типа, C, и он обращается к этому аргументу через ссылку-к-сопзИте параметр, контейнер. Если C является обычным контейнером типа (например, std :: vector), то контейнер будет ссылкой на версию этого контейнера const (например, const std :: vector &). Вызов функции nonmember begin (предоставленный C++ 11) в контейнере const дает команду const_iterator , и этот итератор возвращает этот шаблон.

Например, если я использовал вектор в качестве аргумента для cbegin, как показано ниже.

std::vector<int> v1; 
std::cbegin(v1); 

Теперь посмотрим, как шаблон вычет произошло в этом случае шаблон (класс C) выводится как вектор и параметр cbegin (сопзЬ C & контейнера), выведенную быть const vector<int> &. Теперь, поскольку контейнер сам по себе является постоянным, он будет возвращать постоянную версию начала вектора.

iterator begin(); 
const_iterator begin() const; //This will be used . 
const_iterator cbegin() const; 
Смежные вопросы