Глядя на 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 — это begin(__range) и end(__range) соответственно, где begin и end ищутся с помощью поиска, зависящего от аргумента (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.