C ++ OutputIterator Post-Inkrement-Anforderungen

9

C ++ erfordert, dass ein OutputIterator-Typ X unterstützt Ausdrücke der Form r++ , wobei r eine Instanz von X ist. Dieses Postfixinkrement muss semantisch äquivalent sein zu:

(*) { X tmp = r; ++r; return tmp; }

und muss einen Typ zurückgeben, der in X const& konvertierbar ist. In C ++ 11, siehe 24.2.4 (dies ist jedoch nicht neu). Im selben Abschnitt heißt es

  
    

Algorithmen in Ausgabe-Iteratoren sollten niemals versuchen, denselben Iterator zweimal zu durchlaufen. Sie sollten single pass Algorithmen sein.

  

Gegeben (*), oben, sagen wir, ich kopiere den Rückgabewert wie X a(r++);

  1. Angenommen, r wurde vor dem Inkrementieren dereferenziert, wurde aber nicht dereferenziert. Ist es erforderlich, dass a dereferenzierbar ist? Wenn ja, muss X a(r++); *a = t; die gleiche Zuweisung ausführen wie *r++ = t; andernfalls? Gibt es (andere) Bedingungen für a und r ?

  2. Angenommen, r wurde vor dem Inkrementieren dereferenziert / zugewiesen, und sein inkrementierter Wert ist (auch) dereferenzierbar. Welche der folgenden (wenn überhaupt) sind klar definiert: *a = t; , (b) ++a; *a = t; , (c) *r = t; ?

Siehe auch das Follow-up: Dereferenzierungs-Zuordnung zu einem doppelt inkrementierten OutputIterator

    
nknight 09.08.2012, 02:52
quelle

1 Antwort

4

Wie Sie feststellen, hat r++ eine funktionierende Semantik

%Vor%

Ich habe den Rückgabewert als X hinzugefügt, weil per 24.2.2: 2 Iterator erfüllt CopyConstructible . Daher ist es legitim, den Rückgabewert von r++ in eine Instanz vom Typ% co_de zu kopieren %.

Als nächstes muss X gültig sein; Dies unterscheidet sich von *r++ = o nur durch die Addition eines Sequenzpunkts, der mit dem Sequenzpunkt nach { const X &a(r++); *a = o; } in der obigen operationalen Semantik Definition zusammenfällt, sodass die zusammengesetzte Anweisung die gleiche Gültigkeit wie der Ausdruck hat Erklärung. Durch den Aufruf von return tmp; hat CopyConstructible die gleiche Gültigkeit und operative Semantik.

Im Fall

%Vor%

das folgende Halten:

  • (a) { X a(r++); *a = o; } ist ungültig, weil dieser Wert des Iterators bereits dereferenziert wurde;

  • (b) *a = o ist ungültig, da dieser Wert des Iterators bereits inkrementiert wurde, was die Anforderung für einen einzigen Durchlauf verletzt, da nur (der neue Wert von) ++a; *a = o inkrementierbar sein muss: per die Anmerkung zu 24.2.4: 2, Algorithmen auf Ausgabe-Iteratoren sollten niemals Versuche, denselben Iterator zweimal zu durchlaufen , obwohl in diesem Kontext nicht angegeben ist, was durch bedeutet;

  • (c) r ist gültig, weil der einzige Unterschied zu *r = o insgesamt das Fortbestehen einer Kopie des ursprünglichen Wertes von *r = o; r++; *r = o ist, die pro r keine semantische Wirkung hat auf den Wert kopiert von.

Eine weitere interessante Frage ist (für eine nichtdereferenzierte CopyConstructible ):

%Vor%

Dies wird nicht direkt vom Standard abgedeckt, aber von r scheint es gültig zu sein.

    
ecatmur 09.08.2012, 13:53
quelle

Tags und Links