2012-08-09 10 views
5

Per die (ausgezeichnet) Frage C++ OutputIterator post-increment requirements beobachten wir, dass für einen dereferenceable und inkrementierbare Wert r von OutputIterator Typ X und Wert o geeigneter Art, die Expressiondereferenzieren-Zuordnung zu einem zweifach erhöht OutputIterator

*r++ = o; 

jedoch ist gültig und äquivalente Semantik

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

hat, ist es immer noch der Fall ist, die a dereferenzieren zuweisbare wenn r in der Zwischenzeit mehr als einmal inkrementiert wurde; Das heißt, ist dieser Code gültig?

Es ist schwierig zu sehen, wie Operationen auf einen Wert sich auf die Gültigkeit von Operationen auf einem anderen Wert auswirken können, aber z. InputIterator (24.2.3) hat, unter den Nachbedingungen von ++r:

Alle Kopien des vorherigen Wertes von r keine länger sind entweder erforderlich die Domäne von == in dereferenceable oder sein wird.

Relevante Abschnitte: 24.2.2 Iterator, 24.2.4 Output Iteratoren, 17.6.3.1 Vorlage Argument Anforderungen.

Auch wenn diese nicht ist erforderlich um gültig zu sein, gibt es Situationen, in denen seine Nicht-Gültigkeit ausnutzen würde bei der Umsetzung unterstützen (w.r.t. Effizienz, Einfachheit) einen OutputIterator Typs, während immer noch die bestehenden Anforderungen zu beobachten?

+1

SGI STL (http://www.sgi.com/tech/stl/OutputIterator.html Fußnote 3) verbietet explizit dieses Verhalten und zwingt eine Folge abwechselnder Inkremente und Dereferenzierungszuweisungen; Diese Anforderung kann ich jedoch nicht aus dem C++ - Standard ableiten. Bedeutet '* nur einmal *' in [24.2.4: 2] genau einmal oder höchstens einmal? – nknight

+0

Diese Antwort: (http://StackOverflow.com/A/4004035/985943) lässt mich denken, dass dieses Verhalten für einen 'ostream_iterator' gültig ist, der nur tatsächlich bei Zuweisung erhöht, andere Inkrementierungsvorgänge ignorierend. Es scheint jedoch nicht, dass alle OutputIterators diese Semantik befolgen müssen. – nknight

+0

@nknight sehr interessant. * nur einmal * erscheint 5 mal im Standard, 3,4: 1 mit einer anderen Bedeutung und bei 5,17: 7, 12,8: 15, 29,6,5: 8 im Sinne * höchstens einmal (aber meist einmal) *. * genau einmal * und * höchstens einmal * jeweils 5 mal erscheinen. Sicher, wenn der Standard die SGI-Beschränkungen vorsieht, hätten sie diese Sprache integriert? – ecatmur

Antwort

2

Dieses Problem wurde im Jahr 2004 als defect 485 angehoben und die Formulierung in n3066 klärt die Frage erfordert, dass ein Output-Iterator nur eine Folge von alternierenden Schritten und dereferenzieren/Zuweisungen unterstützen muß. In Ihrem Beispiel muss also r nach der ersten ++r nicht inkrementierbar sein, es sei denn, es liegt eine dazwischen liegende Dereferenzierung/Zuweisung vor. Dieses Verhalten wird auch von SGI STL gefordert (siehe Fußnote 3). Wie Sie oben erwähnt haben, erschien n3225 ohne die Fixes von n3066, also wurde defect 2035 ausgelöst; aber ach, der Fehler hat es nicht in die veröffentlichte Version von C++ 11 (ISO/IEC 14882: 2011) geschafft. Außerdem

, Defekt 2035 sagt, dass a (von X a(r++);) kann nicht wie *a = 0 verwendet werden:

„Nach dieser Operation [dh ++r] r ist nicht als inkrementierbarer und alle Kopien des vorherigen Wertes erforderlich von r müssen nicht mehr dereferenzierbar oder inkrementierbar sein. "

Es gibt Situationen, in denen dies die Umsetzung (in Bezug auf Einfachheit) helfen können: siehe z.B.this question auf ostream_iterator, wo solche (ungültige) doppelte Inkremente einfach ignoriert werden *this; Nur eine Dereferenzierung/Zuweisung führt dazu, dass ostream_iterator tatsächlich erhöht wird.

Verwandte Themen