instead - for_each() c++
Rango basado en redundancia de definiciĆ³n de sentencia (1)
Mirando n3092, en §6.5.4 encontramos la equivalencia para un ciclo basado en rango para. Luego continúa diciendo a qué __begin
y __end
son iguales. Diferencia entre arreglos y otros tipos, y encuentro esto redundante (también confuso).
Dice que para los tipos de arrays que __begin
y __end
son lo que usted espera: un puntero al primero y un puntero al final del pasado. Luego, para otros tipos, __begin
y __end
son iguales para begin(__range)
y end(__range)
, con ADL. El espacio de nombres std
está asociado, para encontrar el std::begin
y std::end
definido en <iterator>
iterator <iterator>
, §24.6.5.
Sin embargo, si nos fijamos en la definición de std::begin
y std::end
, ambas están definidas para matrices y tipos de contenedores. Y las versiones de matriz hacen exactamente lo mismo que arriba: apuntan a la primera, apuntan a una y más allá del final.
¿Por qué es necesario diferenciar las matrices de otros tipos, cuando la definición dada para otros tipos funcionaría igual de bien, encontrando std::begin
y std::end
?
Algunas citas resumidas por conveniencia:
§6.5.4 El rango basado
for
declaración- si _RangeT es un tipo de matriz, begin-expr y end-expr son __range y __range + __bound, respectivamente, donde __bound es la matriz enlazada. Si _RangeT es una matriz de tamaño desconocido o una matriz de tipo incompleto, el programa está mal formado.
- de lo contrario, begin-expr y end-expr son begin (__ range) y end (__ range), respectivamente, donde begin y end se buscan con búsqueda dependiente del argumento (3.4.2). Para los fines de esta búsqueda de nombres, namespace std es un espacio de nombres asociado.
§24.6.5 rango de acceso
template <class T, size_t N> T* begin(T (&array)[N]);
Devoluciones: matriz.
template <class T, size_t N> T* end(T (&array)[N]);
Devuelve: array + N.
Esto evita un caso de esquina con ADL:
namespace other {
struct T {};
int begin(T*) { return 42; }
}
other::T a[3];
for (auto v : a) {}
Debido a que ADL encuentra otro :: comience cuando la llamada begin(a)
, el código equivalente se rompería y causaría un error de compilación confuso (en la línea de "no se puede comparar int con otro :: T *" como el end(a)
devolvería un T *) o comportamiento diferente (si se definió otro :: final e hizo algo igualmente inesperado).