c++ - geeksforgeeks - ¿La comparación de const_iterator con iterador está bien definida?
print iterator vector c++ (3)
Considere el siguiente código:
#include <vector>
#include <iostream>
int main()
{
std::vector<int> vec{1,2,3,5};
for(auto it=vec.cbegin();it!=vec.cend();++it)
{
std::cout << *it;
// A typo: end instead of cend
if(next(it)!=vec.end()) std::cout << ",";
}
std::cout << "/n";
}
Aquí he introducido un error tipográfico: en la comparación llamé vec.end()
lugar de vec.cend()
. Esto parece funcionar según lo previsto con gcc 5.2. Pero, ¿está realmente bien definido de acuerdo con el Estándar? ¿ const_iterator
pueden comparar con seguridad iterator
y const_iterator
?
La Tabla 96 en el Estándar C ++ 11, en la sección 23.2.1, define la semántica operacional de a.cend()
para cualquier tipo de contenedor X
(incluido std::vector
) de la siguiente manera:
const_cast<X const &>(a).end()
Entonces, la respuesta es sí porque, según esta definición, cend()
refiere al mismo elemento / posición en el contenedor que end()
, y X::iterator
debe ser convertible a X::const_iterator
(un requisito también especificado en la misma tabla ( *) ).
(La respuesta también es sí para begin()
vs. cbegin()
por las mismas razones, como se define en la misma tabla.)
(*) Se ha señalado en los comentarios a otras respuestas que la convertibilidad no implica necesariamente que la operación de comparación i1==i2
siempre funcionará, por ejemplo, si operator==()
es una función miembro del tipo de iterador, la conversión implícita solo se aceptará para el argumento del lado derecho, no para el lado izquierdo. 24.2.5 / 6 estados (sobre los iteradores hacia adelante a
y b
):
Si
a
yb
son anulables,a == b
si y solo si*a
y*b
están vinculados al mismo objeto
A pesar de que los iteradores end()
y cend()
no son excluibles, la declaración anterior implica que el operator==()
debe definirse de tal manera que la comparación sea posible incluso si a
es un constitador y b
no lo es. y viceversa, porque 24.2.5 se trata de iteradores avanzados en general, incluidas las versiones const y non-const, esto queda claro, por ejemplo, a partir de 24.2.5 / 1. Por eso estoy convencido de que la redacción del cuadro 96, que se refiere a la convertibilidad, también implica comparabilidad. Pero como se describe en la respuesta posterior de cpplearner @, esto se ha aclarado explícitamente solo en C ++ 14.
Sorprendentemente, C ++ 98 y C ++ 11 no dijeron que se puede comparar un iterator
con un const_iterator
. Esto lleva al número 179 de LWG y al número 2263 de LWG . Ahora en C ++ 14, esto está explícitamente permitido por § 23.2.1 [container.requirements.general] p7
En las expresiones
i == j i != j i < j i <= j i >= j i > j i - j
donde
i
yj
denotan objetos del tipo deiterator
de un contenedor, cualquiera o ambos pueden ser reemplazados por un objeto del tipoconst_iterator
del contenedor que se refiere al mismo elemento sin cambios en la semántica.
Ver §23.2.1, Tabla 96:
X::iterator
[...]
cualquier categoría de iterador que cumpla con los requisitos del iterador directo.
convertible a
X::const_iterator
Entonces, sí, está bien definido.