Dieses Programm ist schlecht gebildet:
%Vor% i
, ein Unterobjekt des temporären X { }
, kann nicht als lvalue verwendet werden, weil X { }
ein rvalue ist.
Dies wird jedoch im Hintergrund mit GCC 5.2.1 und -Wall
kompiliert:
Wenn der Compiler korrekt ist, kann dieses Mal das nullte Element von (Y { })
, das ein Unterobjekt von (Y { })
ist, als lvalue behandelt werden.
Meine Fragen sind:
Ich glaube, der zweite Fall ist schlecht formuliert, wenn ich einen Defekt lese report 1213 richtig, heißt es:
Da die Subskriptionsoperation als Indirektion durch a definiert ist Pointer-Wert, das Ergebnis eines Subscript-Operators, der auf einen xvalue angewendet wird Array ist ein L-Wert, kein X-Wert. Dies könnte für einige überraschend sein.
und die Auflösung waren die folgenden Änderungen am Entwurf des C ++ - Standardabschnitts 5.2.1 [expr], ( fett gedruckte Abschnitte wurden hinzugefügt und Durchstreichungen wurden entfernt ):
Ein Postfix-Ausdruck gefolgt von einem Ausdruck in eckigen Klammern ist a Postfix-Ausdruck. Einer der Ausdrücke muss den Typ haben "Array von T" oder "Zeiger auf T" und das andere soll eine Unscoped-Enumeration oder einen Integraltyp haben. Das Ergebnis ist
ein lvaluevom Typ "T." Der Typ "T" soll ein vollständig definierter Objekttyp sein.62 Ausdruck E1 [E2] ist (per Definition) identisch mit * ((E1) + (E2)) [Hinweis: siehe 5.3 [expr.unary] und 5.7 [expr.add] für Details von * und + und 8.3.4 [dcl.array] für Details zu Arrays. -end note] , außer dass im Fall eines Array-Operanden das Ergebnis ein Lvalue ist, wenn dieser Operand ist ist sonst ein Lvalue und ein xvalue.
Das Ergebnis von Y{}
ist ein Pr-Wert aus dem Abschnitt 5.2.3
[expr.type.conv] :
In ähnlicher Weise wird ein einfacher Typ-Spezifizierer oder Typname-Spezifizierer gefolgt von a braced-init-list erstellt ein temporäres Objekt des angegebenen Typs direct-list-initialized (8.5.4) mit der angegebenen brained-init-Liste, und sein Wert ist das temporäre Objekt als prvalue.
Also sollte das Ergebnis von (Y { })[0]
ein xvalue sein und daher schlecht gebildet sein, da die Zuweisung einen modifizierbaren lvalue am linken Operanden erfordert:
Der Zuweisungsoperator (=) und die zusammengesetzten Zuweisungsoperatoren sind alle Gruppen von rechts nach links. Alle erfordern a modifizierbarer Lvalue als ihr linker Operand [...]
Den aktualisierten Wortlaut finden Sie im Fehlerbericht im Entwurf des C ++ 14-Standards , so wurde diese Änderung nach C ++ 11 angewendet, kann aber auf C ++ 11 angewendet werden, da dies über einen Fehlerbericht angewendet wurde.
Warum Abschnitt 5.3.1
[expr.unary.op] nicht auch aktualisiert wurde, ist mir unklar, es scheint etwas inkonsistent zu sagen, das Ergebnis ist ein lvalue was Es ist nicht in allen Fällen.
Aktualisieren
Hat einen Spam-Bericht abgelegt.
Der Entwurf des C ++ Standards (N4527) § 5.2.1 Satz 1 besagt:
Der Ausdruck E1 [E2] ist (per Definition) identisch mit * ((E1) + (E2))
§ 5.3.1 Satz 1 sagt:
Der unäre * Operator führt eine Indirektion aus: Der Ausdruck, auf den er angewendet wird, soll ein Zeiger auf einen Objekttyp sein oder ein Zeiger auf einen Funktionstyp und das Ergebnis ist ein lvalue , das sich auf das Objekt bezieht oder Funktion, auf die der Ausdruck zeigt.
Tags und Links c++ c++11 language-lawyer c++14