Глядя на n3092, в §6.5.4 мы находим эквивалентность для цикла for, основанного на диапазоне. Затем он говорит, что __begin
и __end
равны. Он различает массивы и другие типы, и я нахожу это излишним (иначе запутанным).
В типах массивов сказано, что __begin
и __end
- это то, что вы ожидаете: указатель на первое и указатель на один за концом. Тогда для других типов __begin
и __end
равны begin(__range)
и end(__range)
с ADL. Пространство имен std
связано, чтобы найти std::begin
и std::end
, определенные в <iterator>
, § 24.6.5.
Однако, если мы посмотрим на определения std::begin
и std::end
, они оба определены для массивов, а также для типов контейнеров. И версии массива работают точно так же, как и выше: указатель на первый, указатель на один за концом.
Почему существует необходимость отличать массивы от других типов, когда определение, данное для других типов, будет работать так же хорошо, находя std::begin
и std::end
?
Некоторые сокращенные цитаты для удобства:
§6.5.4 Оператор for
на основе диапазона
- если _RangeT является типом массива, begin-expr и end-expr имеют значения __range и __range + __bound соответственно, где __bound является границей массива. Если _RangeT является массивом неизвестного размера или массивом неполного типа, программа некорректна.
- в противном случае begin-expr и end-expr начинаются (диапазон __) и заканчиваются (диапазон __) соответственно, где начало и конец ищутся в зависимости от аргументов (3.4.2). Для целей этого поиска имени пространство имен std является связанным пространством имен.
§24.6.5 диапазон доступа
template <class T, size_t N> T* begin(T (&array)[N]);
Возвращает: массив.
template <class T, size_t N> T* end(T (&array)[N]);
Возвращает: массив + N.