2012-08-09 12 views
5

Per la (eccellente) domanda C++ OutputIterator post-increment requirements, osserviamo che per un valore dereferenceable e incrementabile r di OutputIterator tipo X, e il valore o di tipo appropriato, l'espressionerisoluzione del riferimento di assegnazione di un OutputIterator doppiamente incrementato

*r++ = o; 

è valido e ha una semantica equivalenti a

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

Tuttavia, è ancora il caso della a è dereferenziamento assegnabili se r è stato incrementato più volte nel periodo intermedio; cioè, questo codice è valido?

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

E 'difficile vedere come operazioni su un valore può avere un effetto sulla validità delle operazioni su un altro valore, ma per esempio InputIterator (24.2.3) ha, sotto le post di ++r:

qualsiasi copia del valore precedente di r sono necessaria più né di essere dereferenceable o di essere in dominio della ==.

sezioni rilevanti: 24.2.2 Iterator, 24.2.4 iteratori uscita, 17.6.3.1 requisiti argomento di template.

Inoltre, se questo è non necessaria per essere valido, vi sono situazioni in cui sfruttano la non validità aiuterebbe nell'attuazione (efficienza w.r.t., semplicità) di un tipo OutputIterator pur rispettando i requisiti esistenti?

+1

SGI STL (http://www.sgi.com/tech/stl/OutputIterator.html footnote 3) vieta esplicitamente questo comportamento, forzando una sequenza di incrementi alternati e assegnazioni di dereferenziazione; tuttavia, non posso derivare tale requisito dallo standard C++. '* Solo una volta *' in [24.2.4: 2] significa esattamente una volta o al massimo una volta? – nknight

+0

Questa risposta: (http://stackoverflow.com/a/4004035/985943) mi fa pensare che questo comportamento sia valido per un 'ostream_iterator', che di fatto incrementa solo l'assegnazione, ignorando altre operazioni di incremento. Tuttavia, non sembra che tutti gli OutputIterator debbano obbedire a quella semantica. – nknight

+0

@nknight molto interessante. * solo una volta * appare 5 volte nello standard, a 3.4: 1 con un significato diverso, e a 5.17: 7, 12.8: 15, 29.6.5: 8 nel senso * al massimo una volta (ma solitamente una volta) *. * esattamente una volta * e * al massimo una volta * ciascuna appare 5 volte. Sicuramente se lo standard intendesse le restrizioni SGI, avrebbero incorporato quella lingua? – ecatmur

risposta

2

Questo problema è stato sollevato nel 2004 come defect 485, e la formulazione n3066 chiarisce la questione, richiedendo che un iteratore di uscita deve supportano solo una sequenza di incrementi alternati e dereferenziare/assegnazioni. Pertanto, nel tuo esempio, r non deve essere incrementabile dopo il primo ++r, a meno che non vi sia un distacco/assegnazione intermedio. Questo comportamento è richiesto anche da SGI STL (vedi nota 3). Come accennato in precedenza, n3225 è apparso senza le correzioni da n3066, quindi è stato generato defect 2035; ma purtroppo la correzione non è riuscita a farla diventare la versione pubblicata di C++ 11 (ISO/IEC 14882: 2011).

Inoltre, difetto 2035 afferma che a (da X a(r++);) non possono essere utilizzati come *a = 0:

"Dopo questa operazione [cioè, ++r] r non è richiesto di essere incrementabile e qualsiasi copia del valore precedente di r non sono più necessari per essere dereferenziabili o incrementabili. "

Ci sono situazioni in cui puo aiutare l'attuazione (in termini di semplicità ): si veda per esthis question su ostream_iterator, dove tali doppi incrementi (non validi) vengono ignorati semplicemente restituendo *this; solo un dereferenziamento/assegnazione fa sì che lo ostream_iterator incrementi effettivamente.

Problemi correlati