2015-03-26 11 views
7

Der folgende Code kompiliert und ausgeführt in gcc 4.9.1 und clang-3.6 bei Verwendung von -std = C++ 11:Initialisierung des statischen constexpr Element-Array in gcc 4.8

struct Bar 
{ 
    int x; 
}; 

struct Foo 
{ 
    static constexpr Bar bars[] = {1, 2, 3}; 
}; 

constexpr Bar Foo::bars[]; 

Jedoch versagt es in gcc 4.8.3, was zu der Fehlermeldung

./cpptest.cpp:14:43: error: could not convert '1' from 'int' to 'const Bar' 
    static constexpr Bar bars[] = {1, 2, 3}; 
             ^
./cpptest.cpp:14:43: error: could not convert '2' from 'int' to 'const Bar' 
./cpptest.cpp:14:43: error: could not convert '3' from 'int' to 'const Bar' 

Übrigens, wenn ich das gleiche tun, aber bars eine statische const globale Array machen, kompiliert es in gcc 4.8 und Klappern in Ordnung. Es wird auch gut kompilieren, wenn ich jedes der Integer-Literale in der Liste mit einem zusätzlichen Paar {} umgeben.

Also ist das ein Fehler in gcc 4.8? Was sagt der Standard dafür? Welcher Teil des einheitlichen Initialisierungsstandards C++ 11 wird aufgerufen, wenn ich die zusätzlichen Klammern weglasse?

Bearbeiten: Es sieht aus wie der Standard besagt, dass dies Aggregat Initialisierung aufrufen sollte, die für "Klammer Elision" ermöglichen sollte. Es scheint also, dass es ein Fehler in gcc 4.8 ist, der von gcc 4.9 behoben wurde, aber ich bin überhaupt nicht zuversichtlich, den Standard zu lesen. Ich kann auch keinen Bugreport in gcc's Bug Tracker finden, deswegen könnte ich leicht falsch liegen.

+0

Haben Sie es als Fehler betrachtet, der behoben wurde? – edmz

Antwort

2

Um das zu tun, was Sie tun möchten, können Sie einen constexpr Konstruktor innerhalb Foo angeben:

struct Bar 
{ 
    constexpr Bar(int c) : x(c) 
    {} 

    int x; 
}; 

struct Foo 
{ 
    static constexpr Bar bars[] = {1, 2, 3}; 
}; 

constexpr Bar Foo::bars[]; 

Offenbar gcc 4.8.3 implicity nicht die Werte innerhalb der geschweiften Klammern konvertieren Objekte Bar, während gcc 4.9.1 tut.

+0

Sicher, und das ist die Route, die ich am Ende ging. Dies ergab einen weiteren Fehler in gcc 4.9 (den ich hier gemeldet habe: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65695). Aber meine Frage ist, sollte der Standard die Initialisierung ohne diese Klammern erlauben? Und ich denke, die Antwort ist ja, es ist einfach ein Fehler in GCCs Handhabung von Klammern mit Constexpr-Mitgliedern. –

+0

Ich würde das nicht als Bug bezeichnen. GCC verlangt von Ihnen lediglich, einen consExpr-Konstruktor zu deklarieren, wenn Sie eine consExpr-Variable deklarieren. Ich habe mir auch Ihren Fehlerbericht angesehen und darauf geantwortet. Was Sie dort tun möchten, sollte nicht funktionieren: Sie sollten nicht in der Lage sein, die Adresse einer nicht statischen Mitgliedsfunktion in einer statischen Variablen zu speichern. – kamshi

+0

GCC 4.8 behauptet, den Standard ISO/IEC 14882: 2011 (C++ 11) zu unterstützen. Wenn der Fehler, Klammer Elision zu verletzen, den Standard verletzt (und ich bin mir ziemlich sicher, dass es tut), dann ist es ein Fehler in GCC 4.8. Und in ähnlicher Weise hat der Standard einen Abschnitt über konstante Ausdrücke. Es gibt eine lange Liste von Dingen, die keine konstanten Ausdrücke sind. Basierend auf meinem (zugegebenermaßen Amateur-) Lesen des Standards ist die Adresse einer nicht statischen Elementfunktion ein konstanter Ausdruck. –