undefinierter Verweis beim Zugriff auf das statische consExpr Float-Element

8

Dieser Code funktioniert:

%Vor%

Aber wenn ich int in float ändere, bekomme ich einen Fehler:

%Vor%
  

/tmp/main-272d80.o: In der Funktion main': main.cpp:(.text+0xe): undefined reference to Blob :: a '

Warum kann ich nicht constexpr float auf diese Weise verwenden?

Compiler: Ubuntu-Sprachversion 3.5.0-4ubuntu2 (tags / RELEASE_350 / final)

Getestet auf gcc Version 4.9.1 (Ubuntu 4.9.1-16ubuntu6) und es gab keinen Fehler.

BEARBEITEN:

Es wird kompiliert, wenn ich -O1, -O2, -O3 oder -Os verwende, aber mit -O0

versagt     
Anonymous Entity 01.02.2015, 15:20
quelle

2 Antworten

6

C ++ 11 liest

  

Eine Variable, deren Name als potenziell ausgewerteter Ausdruck erscheint    odr-used es sei denn, es ist ein Objekt, das die Anforderungen für erfüllt   erscheint in einem konstanten Ausdruck (5.19) und dem Wert lvalue-to-r   Umwandlung (4.1) wird sofort angewendet.

Offensichtlich wird die l-t-r-Umwandlung sofort angewendet, und eine constexpr -Variable vom Fließkommatyp kann in konstanten Ausdrücken erscheinen wie in [expr.const] / (2.7.1):

  

Ein ist ein -Kernkonstantenausdruck , es sei denn,   umfasst einen der folgenden als potenziell ausgewerteten Unterausdruck   [..]

     
  • eine lvalue-to-rvalue-Konvertierung (4.1), wenn sie nicht angewendet wird      
    • Ein glvalue des Literaltyps, der sich auf ein nicht-flüchtiges Objekt bezieht, das mit constexpr definiert ist, oder das sich auf ein Unterobjekt eines solchen Objekts bezieht   Objekt oder
    •   
  •   

Scheint ein Clang-Bug zu sein.

    
Columbo 01.02.2015, 15:57
quelle
3

Interessanterweise, wenn wir stattdessen Blob::a verwenden, klagt clang nicht:

%Vor%

Dies sollte nicht wichtig sein, um festzustellen, ob es odr-verwendet wird oder nicht. Das sieht also wie ein clang Bug aus, den ich auf clang 3.7 reproduzieren kann, ohne nur eine Optimierung zu verwenden. Wir können feststellen, dass dies ein odr Problem ist, da das Hinzufügen einer Out-of-Class-Definition das Problem behebt ( live sehen ) / em>):

%Vor%

Wann müssen Sie ein statisches Mitglied der consExpr-Klasse definieren? Dies wird im Abschnitt 9.4.2 [class.static.data] behandelt, der besagt ( Hervorhebung meiner Zukunft ):

  

Ein statisches Datenelement des Literaltyps kann in der Klasse deklariert werden   Klassendefinition mit dem consExpr-Spezifizierer; Wenn ja, muss in der Deklaration ein "brace-or-equal-initializer" angegeben werden   in dem jede Initializerklausel, die ein Zuweisungsausdruck ist, ein konstanter Ausdruck ist. [Anmerkung: In beiden   In diesen Fällen kann das Element in konstanten Ausdrücken angezeigt werden. -end note] Das Mitglied soll noch definiert werden   in einem Namespace-Bereich, wenn es im Programm odr-used (3.2) ist und die Namespace-Bereichsdefinition nicht   enthält einen Initialisierer.

Es erfordert eine Definition, wenn es odr-verwendet wird. Ist es odr-used? Nein ist es nicht. Der ursprüngliche C ++ 11-Wortlaut im Abschnitt 3.2 [basic.def.odr] lautet:

  

Ein Ausdruck wird möglicherweise ausgewertet, es sei denn, es handelt sich um einen nicht bewerteten Operanden (Abschnitt 5) oder einen Unterausdruck   davon. Eine Variable, deren Name als potenziell evaluierter Ausdruck erscheint, wird odr-verwendet, es sei denn ist ein   Objekt, das die Anforderungen erfüllt, damit es in einem konstanten Ausdruck erscheint (5.19) und der Wert von lvalue-to-r   Konvertierung (4.1) wird sofort angewendet .

a erfüllt beide Bedingungen, es ist ein konstanter Ausdruck und die lvalue-to-rvalue-Konvertierung wird sofort angewendet. Fehlerbericht 712 hat den für C ++ 11 geltenden Wortlaut geändert da es sich um einen Fehlerbericht handelt und 3.2 jetzt sagt:

  

Eine Variable x, deren Name als potenziell evaluierter Ausdruck ex angezeigt wird, wird verwendet, es sei denn wird angewendet   Lvalue-to-rvalue-Konvertierung (4.1) zu x ergibt einen konstanten Ausdruck (5.19), der kein nicht-triviales aufruft   Funktionen und, wenn x ein Objekt ist, ist ex ein Element der Menge möglicher Ergebnisse eines Ausdrucks e, wobei   entweder wird die lvalue-to-rvalue-Konvertierung (4.1) auf e angewendet, oder e ist ein Ausdruck mit verworfenem Wert

Das mögliche Ergebnis, das zutrifft, wäre:

  

Wenn e ein ID-Ausdruck (5.1.1) ist, enthält die Menge nur e.

es ist ein konstanter Ausdruck und die lvalue-to-rvalue-Konvertierung wird angewendet, so dass es nicht odr-used ist.

    
Shafik Yaghmour 11.02.2015 19:22
quelle