2012-08-09 18 views
5

Per la (excelente) pregunta C++ OutputIterator post-increment requirements, se observa que para un valor Dereferenceable y incrementable r de OutputIterator tipo X, y el valor o de tipo apropiado, la expresiónDesreferencia-asignación a una OutputIterator doblemente incrementado

*r++ = o; 

es válida y tiene la semántica equivalentes a

X a(r); 
++r; 
*a = o; 

Sin embargo, es todavía el caso del a es eliminar la referencia asignable si r se ha incrementado más de una vez en el intervalo; es decir, ¿este código es válido?

X a(r); 
++r; 
++r; 
*a = o; 

Es difícil ver cómo las operaciones de un valor pueden tener un efecto sobre la validez de las operaciones en otro valor, pero por ejemplo, InputIterator (24.2.3) tiene, en virtud de las condiciones posteriores de ++r:

cualquier copia de los valor anterior de r hay más largo requerido ya sea para ser Dereferenceable o estar en el dominio de ==.

secciones pertinentes: 24.2.2 Iterator, 24.2.4 iteradores de salida, 17.6.3.1 requisitos argumento de plantilla.

Además, si esto es no requiere para su validez, ¿hay situaciones en las que explotan su falta de validez ayudaría en la aplicación (eficiencia, simplicidad w.r.t.) de un tipo OutputIterator mientras sigue observando los requisitos existentes?

+1

SGI STL (http://www.sgi.com/tech/stl/OutputIterator.html nota al pie 3) explícitamente prohíbe este comportamiento, forzando una secuencia de incrementos alternantes y asignaciones de desreferencia; sin embargo, no puedo derivar ese requerimiento del estándar C++. ¿'* Solamente una vez *' en [24.2.4: 2] significa exactamente una vez o como mucho una vez? – nknight

+0

Esta respuesta: (http://stackoverflow.com/a/4004035/985943) me hace pensar que este comportamiento es válido para un 'ostream_iterator', que solo aumenta la asignación, ignorando otras operaciones de incremento. Sin embargo, no parece que todos los OutputIterators deben obedecer esas semánticas. – nknight

+0

@nknight muy interesante. * solo una vez * aparece 5 veces en el estándar, en 3.4: 1 con un significado diferente, y en 5.17: 7, 12.8: 15, 29.6.5: 8 en el sentido * como máximo una vez (pero generalmente una vez) *. * exactamente una vez * y * como máximo una vez * cada uno aparece 5 veces. Seguramente si el estándar pretendía las restricciones de SGI, ¿habrían incorporado ese idioma? – ecatmur

Respuesta

2

Este problema se planteó en 2004 como defect 485, y la redacción en n3066 aclara el problema, requiriendo que un iterador de salida solo necesite soportar una secuencia de incrementos alternantes y desreferencia/asignaciones. Por lo tanto, en su ejemplo, r no necesita ser incrementable después del primer ++r, a menos que haya una desreferencia/asignación intermedia. Este comportamiento también es requerido por SGI STL (ver nota 3). Como mencionó anteriormente, n3225 apareció sin las correcciones de n3066, por lo que defect 2035 se planteó; pero, por desgracia, la solución no llegó a la versión publicada de C++ 11 (ISO/IEC 14882: 2011).

Además, defecto 2035 dice que a (de X a(r++);) no se puede utilizar como *a = 0:

"Después de esta operación [es decir, ++r] r no se requiere para ser incrementable y cualquier copia del valor previo de r ya no se requiere que sean derivables o incrementables ".

hay situaciones en las que esto puede ayudar a la aplicación (en términos de simplicidad ): véase, por ejemplothis question en ostream_iterator, donde tales incrementos dobles (inválidos) se ignoran simplemente devolviendo *this; solo una desreferencia/asignación hace que el ostream_iterator aumente realmente.

Cuestiones relacionadas