2015-03-27 25 views
6

non sono sicuro se questo è un bug del compilatore o se ho capito male constexpr:perché una variabile di constexpr non inizializzata non è costante?

struct S{}; 
constexpr S s1{}; 
constexpr S s2; 

struct test{ 
    static constexpr auto t1 = s1; 
    static constexpr auto t2 = s2; //error here 
}; 

GCC 4.8 mi sta dando un errore strano "errore: campo inizializzatore non è costante". S2 non è davvero una costante? Se è così, perché?

Per chiarezza, in realtà sto usando un mucchio di strutture vuote nel mio codice (per la meta programmazione https://github.com/porkybrain/Kvasir) quindi sono davvero interessato a questo esempio specifico.

+0

Per clang, * l'inizializzazione predefinita di un oggetto di tipo const 'const S' richiede un costruttore predefinito fornito dall'utente * [Demo] (http://coliru.stacked-crooked.com/a/858633b06d501e42) – Jarod42

risposta

4

Update: Il codice dovrebbe compilare, perché [class.ctor]/5 legge:

The implicitly-defined default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with no ctor-initializer (12.6.2) and an empty compound-statement. If that user-written default constructor would satisfy the requirements of a constexpr constructor (7.1.5), the implicitly-defined default constructor is constexpr .

E poiché S è solo uno struct vuoto, il costruttore di default definito implicitamente è vuoto e quindi soddisfacente constexpr requisiti.

Quindi qui si tratta dell'imperfezione dei compilatori, che in qualche modo devi risolvere in qualche modo.


Vecchia risposta:

Clang emette messaggio di errore più sensata:

main.cpp:3:13: error: default initialization of an object of const type 'const S' 
requires a user-provided default constructor 
constexpr S s2; 
      ^

[dcl.constexpr]/9 fornisce la spiegazione e anche quasi esattamente il codice come un esempio:

A constexpr specifier used in an object declaration declares the object as const. Such an object shall have literal type and shall be initialized.(...) [ Example:

struct pixel { 
    int x, y; 
}; 
constexpr pixel ur = { 1294, 1024 };// OK 
constexpr pixel origin; // error: initializer missing 

—end example ]

+0

Probabilmente non dovrebbe essere necessario per una struttura vuota, e penso che ci fosse una proposta per cambiare lo standard per esso. Non riesco a cercarlo ora (i commenti sono abbastanza difficili su un telefono) ma se riesci a trovarlo potrebbe valere la pena includerlo nella tua risposta. – hvd

+0

Fornire un costruttore predefinito 'constexpr' abilita la definizione di' s2' senza un inizializzatore, come suggerito dal messaggio di errore 'clang'. È interessante notare che, mentre gcc accetta 'constexpr S() = default;', clang non (come da 3.6). Credo che clang sia in errore, poiché [dcl.constexpr]/4 consente questa dichiarazione, [dcl.constexpr]/9 richiede solo un'espressione costante, e [expr.const] tratta questo caso come qualsiasi altro costrutto 'constexpr', ma in pratica ciò significa che 'constexpr S() {}' è richiesto per la portabilità. – Wintermute

+0

@Wintermute Ora sono in dubbio perché secondo '[class.ctor]/5' il ctor implicito predefinito per' S' dovrebbe essere 'constexpr', quindi il codice dovrebbe essere compilato così com'è. –

Problemi correlati