Основанный на диапазоне для дублирования определения оператора

При рассмотрении 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.

19
задан ildjarn 29 October 2011 в 17:38
поделиться

1 ответ

Это позволяет избежать углового случая с 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 был определен и сделал нечто похожее неожиданное).

22
ответ дан 30 November 2019 в 04:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: