print geeksforgeeks for c++ iterator comparison-operators const-iterator

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 y b 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 y j denotan objetos del tipo de iterator de un contenedor, cualquiera o ambos pueden ser reemplazados por un objeto del tipo const_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.