Могу ли я использовать функции доступа библиотек итераторов к нестандартным контейнерам?

В библиотеке iterator было представлено множество функций доступа по ходу C+. +11, С++ 14 и С++ 17:

  • begin/end
  • cbegin/cend
  • crbegin/crend
  • data
  • empty
  • rbegin/rend
  • size

Могу ли я использовать их в любом контейнере, даже в нестандартном контейнере (при условии, что они предоставляют доступный соответствующий метод?). Например, при наличии QVector foo можно сделать так:

const auto bar = begin(foo);

person Jonathan Mee    schedule 29.06.2016    source источник
comment
Почему бы вам не быть в состоянии? Все, что они делают, это вызывают соответствующую функцию-член.   -  person NathanOliver    schedule 29.06.2016
comment
Вы можете, если: (а) ваш класс предоставляет соответствующие функции-члены; или (b) вы предоставляете перегрузки, специфичные для вашего класса.   -  person Innocent Bystander    schedule 29.06.2016


Ответы (2)


Объявления для std::begin следующие (из 24.7):

template <class C> auto begin(C& c) -> decltype(c.begin());
template <class C> auto begin(const C& c) -> decltype(c.begin());

Таким образом, эти функции будут определены для любого класса C такого, что c.begin() является «действительным» (существует). Стандарт также гарантирует, что они будут:

Возвращает: c.begin().

Итак, да, вы можете использовать begin(c) в любом контейнере типа C, если:

  • Предоставляется функция-член C::begin().
  • Существуют функции begin(C const&) или begin(C &).

Автономная функция begin должна находиться не в пространстве имен std::, а в том же пространстве имен, что и ваш класс C, чтобы ее можно было найти с помощью поиска по имени.

person Holt    schedule 29.06.2016

Как я понимаю, ваш вопрос звучит так: если контейнер предоставляет функцию-член begin, могу ли я вызвать ее как бесплатную функцию? Ответ на ваш вопрос - да, потому что шаблонная бесплатная функция begin предоставляется стандартом, который просто пытается вызвать функцию-член begin; из http://en.cppreference.com/w/cpp/iterator/begin: "Возвращает итератор в начало заданного контейнера c или массива массивов. Эти шаблоны полагаются на то, что C::begin() имеет разумную реализацию.".

person Nir Friedman    schedule 29.06.2016