2015-03-26 24 views
7

Il seguente codice compilato ed eseguito in gcc 4.9.1 e clang-3.6 utilizzando -std = C++ 11:Inizializzazione statica matrice membro constexpr in gcc 4.8

struct Bar 
{ 
    int x; 
}; 

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

constexpr Bar Foo::bars[]; 

Tuttavia, non riesce a gcc 4.8.3, con conseguente messaggio di errore

./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' 

per inciso, se faccio la stessa cosa ma fare bars una matrice globale static const, si compila bene in gcc 4.8 e clang. Compilerà anche bene se io copro tutti i letterali interi della lista con una coppia extra di {}.

Quindi questo è un bug in gcc 4.8? Che cosa dice lo standard è la sintassi appropriata per questo? Quale parte dello standard di inizializzazione uniforme del C++ 11 viene invocato quando ometto le parentesi graffe?

Modifica: Sembra che lo standard indichi che questo dovrebbe richiamare l'inizializzazione di aggregazione, che dovrebbe consentire "brace elision". Quindi sembra che sia un bug in gcc 4.8, che è stato corretto da gcc 4.9, ma non sono affatto sicuro della mia lettura dello standard. Anche io non riesco a trovare alcun bug report nel bug tracker di gcc su questo, quindi potrei facilmente sbagliare.

+0

Hai considerato un errore risolto? – edmz

risposta

2

Per fare ciò che si vuole fare, è necessario specificare un costruttore constexpr all'interno Foo:

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

    int x; 
}; 

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

constexpr Bar Foo::bars[]; 

4.8.3 A quanto pare gcc non implicitamente convertire i valori all'interno delle parentesi graffe a Bar oggetti, mentre gcc 4.9.1 lo fa.

+0

Certo, e questa è la strada che ho finito per andare giù. Questo ha finito per esporre un altro bug in gcc 4.9 (che ho riportato qui: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65695). Ma la mia domanda è, dovrebbe lo standard consentire l'inizializzazione senza quelle parentesi? E penso che la risposta sia sì, è semplicemente un bug nella gestione di gild elision di gcc con i membri di constexpr. –

+0

Non lo chiamerei bug. GCC richiede semplicemente che tu dichiari un costruttore di constexpr quando dichiari una variabile di constexpr. Ho anche esaminato la tua segnalazione di bug e ho risposto ad essa. Quello che vuoi fare non dovrebbe funzionare: non dovresti essere in grado di memorizzare l'indirizzo di una funzione membro non statico in una variabile statica. – kamshi

+0

GCC 4.8 afferma di supportare lo standard ISO/IEC 14882: 2011 (C++ 11). Se la mancata autorizzazione di elision brace viola lo standard (e sono abbastanza sicuro che lo faccia), allora è un bug in GCC 4.8. E, analogamente, lo standard ha una sezione sulle espressioni costanti. Fornisce una lunga lista di cose che non sono espressioni costanti. Basato sulla mia lettura (certamente amatoriale) dello standard, l'indirizzo di una funzione membro non statico è un'espressione costante. –

Problemi correlati