Verwenden eines temporären Arrays als Lvalue

8

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:

%Vor%

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:

  1. Ist das zweite Programm schlecht gebildet?
  2. Warum (nicht), obwohl beide Programme ein Unterobjekt eines temporären als lvalue zu behandeln scheinen?
J. Doe 16.10.2015, 01:14
quelle

2 Antworten

8

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 lvalue vom 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.

    
Shafik Yaghmour 16.10.2015, 02:03
quelle
3

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.

    
Nicky C 16.10.2015 01:26
quelle

Tags und Links