При рассмотрении n3092, в §6.5.4 мы находим эквивалентность для основанного на диапазоне для цикла. Это затем продолжает что __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 является типом массива, начните-expr, и конец-expr __ диапазон и __ диапазон + __ связан, соответственно, где __ связанный связанный массив. Если _RangeT является массивом неизвестного размера или массивом неполного типа, программа плохо формируется.
— иначе начните-expr, и конец-expr, начинаются (__ диапазон) и конец (__ диапазон), соответственно, где начинаются, и конец ищутся с зависимым от аргумента поиском (3.4.2). В целях этого поиска имени станд. пространства имен является связанным пространством имен.
Доступ диапазона §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.
Это позволяет избежать углового случая с ADL:
namespace other {
struct T {};
int begin(T*) { return 42; }
}
other::T a[3];
for (auto v : a) {}
Поскольку ADL находит other :: begin при вызове begin (a)
, эквивалентный код сломается, что приведет к сбивающей с толку ошибке компиляции (по строкам «невозможно сравнить int с другими :: T *», поскольку end (a)
вернет T *) или другое поведение (если other :: end был определен и сделал нечто похожее неожиданное).