2013-12-18 12 views
5

Ich stolperte über den Code, den ich nicht verstehe. Hier ist eine vereinfachte Version davon:C++ 98 geschweifte Klammer const skalare Initialisierung

template <int> struct A {}; 

int const i = { 42 }; 
typedef A<i> Ai; 

int const j = 42; 
typedef A<j> Aj; 

Dieser Code kompiliert mit GCC in C++ 98-Modus, aber nicht in Clang. Clang erzeugt den folgenden Fehler:

$ clang -Wall -Wextra -std=c++98 -c test.cpp 

test.cpp:4:11: error: non-type template argument of type 'int' is not an integral constant expression 
typedef A<i> Ai; 
     ^
test.cpp:4:11: note: initializer of 'i' is not a constant expression 
test.cpp:3:11: note: declared here 
int const i = { 42 }; 
     ^

Soweit ich verstehe Initialisierung von int mit und ohne geschweifte Klammern sollten gleichwertig sein. Clang initialisiert i korrekt zu 42, einfach nicht, dass es eine Kompilierzeitkonstante ist.

Dieser Code kompiliert gut in C++ 11-Modus.

Gibt es einen Grund j wird als Kompilierzeitkonstante behandelt und i ist nicht? Oder ist es einfach ein Fehler in Clang?

Update: Ich öffnete eine ticket in LLVM Bug Tracker mit diesem Problem.

+0

ich würde sagen, dass es ein Fehler in dem Compiler ist. – Raxvan

+2

@Raxvan: Das ist eine ziemlich kühne Aussage ... In Anbetracht der Tatsache, dass es in C++ 11 und nicht in C++ 98 funktioniert, scheint es ziemlich absichtlich zu sein, also würde ich erwarten, dass es * nach den Spezifikationen * ist (auf Clang-Teil) und gcc ist wie üblich nachsichtiger. –

+0

@MatthieuM .: Ich denke, dass das ist, was er sagen wollte: Es ist ein Fehler in gcc. Es gibt keine C++ 98-Syntax dafür, und clang lehnt dies zu Recht ab. Es ist also ein Fehler, es in gcc zu akzeptieren, obwohl es nicht C++ 98 ist. – PlasmaHH

Antwort

2

Der Compiler-Fehler besagt, dass "template argument of type 'int' is not an integral constant expression" für int const i = { 42 };

Nach 98 standard das Template-Argument in diese Kategorie fallen sollte:

14.3.2/1

A template-argument for a non-type, non-template template-parameter shall be one of:

  • an integral constant-expression of integral or enumeration type; or

...

und die Definition der Integralkonstanten Ausdruck int const i fa ll in diese Kategorie:

5.19 Constant expressions

An integral constant-expression can involve only literals (2.13), enumerators, const variables or static data members

und für die Initialisierung von i (wie Mike Seymour post):

8.5 Initializers /13

If T is a scalar type, then a declaration of the form

T x = { a };

is equivalent to

T x = a;

nun basierend auf this post die Deklaration von const int und int const sollten gleich sein (konnte nicht gefunden dies speziell im Standard) machen i ein const Variable. Jede Verwendung von i sollte unabhängig von der Initialisierungsmethode ein konstanter Ausdruck sein. Es scheint, dass es einen Fehler beim Klingeln gibt.die Web-Überprüfung kann ich nicht einen Fehlerbericht nur zwei mehr oder weniger ähnlich finden:

http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=666539

und

http://lists.cs.uiuc.edu/pipermail/llvmbugs/2011-March/017353.html

5

Ja, beide Erklärungen äquivalent sind, pro C 98 ++ 8.5/13:

If T is a scalar type, then a declaration of the form

T x = { a }; 

is equivalent to

T x = a; 

So beide Variablen konstant sind, und von einem konstanten Ausdruck initialisiert, so (soweit ich sehen kann) sollten beide als konstante Ausdrücke verwendbar sein.

1

Ich denke, dass Clang Recht hat. Initialisierungsliste ist kein Ausdruck. Es gibt einen Unterschied zwischen der Initialisierung von Aggregatobjekten und fundamentalen Objekten. Wenn ein POD-Objekt initialisiert wird, kann jeder Initialisierer als ein konstanter Ausdruck betrachtet werden. Wenn Sie jedoch mit grundlegenden Typen arbeiten, ist die Initialisiererliste kein Ausdruck und kein Const-Ausdruck.

In Ziffer # 14 der Norm wird geschrieben:

The source type is not defined when the initializer is brace-enclosed or when it is a parenthesized list of expressions

Verwandte Themen