2016-02-26 15 views
5

Si consideri il seguente codice (available on gcc.godbolt.org):Utilizzando un lambda in un `funzione di constexpr` in un contesto non-`constexpr`: clang vs gcc

template <typename TF> 
constexpr auto fn_x(TF f) 
{ 
    return f(); 
} 

constexpr auto get_x() 
{ 
    return fn_x([]{ return 0; }); 
} 

int main() 
{ 
    auto res = get_x(); 
} 

Compila sotto g ++ 5.3.x e più recente (incluso g ++ 6.xx).

non si compila sotto clang ++ 3.7.x e più nuovo con il seguente errore:

error: constexpr function never produces a constant expression [-Winvalid-constexpr] 
constexpr auto get_x() 
      ^
note: subexpression not valid in a constant expression 
     return fn_x([]{ return 0; });       

Una soluzione possibile per rendere il codice compilare sia con gcc e clang utilizza un "livello di riferimento indiretto" con decltype, anche eliminare lo constexpr nella funzione in cui è definito il lambda: gcc.godbolt.org link.

Quale compilatore è corretto in base allo standard?

+0

In ogni caso, forse più pertinente alla tua domanda: fai uno qualsiasi dei compilatori che collaudi affermando che 'get_x()' può essere usato in un'espressione costante? In caso contrario, è la tua domanda "sono autorizzato ad aggiungere' constexpr' a funzioni che non possono mai essere utilizzate in espressioni costanti? " – hvd

+0

@hvd: Riguardo al punto e virgola, compilo sempre codice reale con '-Wpedantic', che mi informa dell'errore. Sono abituato a scrivere codice lambda-pesante ('auto l = [] {...};') così a volte il mio cervello aggiunge automaticamente un punto e virgola alla fine di una funzione. –

+0

@hvd È valido C++ 11 - il ';' è una * dichiarazione vuota *. Vedi [CWG 569] (http://wg21.link/cwg569). –

risposta

6

Entrambi i compilatori concordano che get_x() non può essere utilizzato in un'espressione costante. Puoi dire cambiando auto res = get_x(); a constexpr auto res = get_x();, dove GCC lo rifiuterà allo stesso modo.

quanto per rilevare che al momento definizione di funzione come clang fa anziché alla funzione utilizzare come gcc non, sono consentiti entrambi: (sottolineatura mia)

7.1.5 The constexpr specifier [dcl.constexpr]

5 For a non-template, non-defaulted constexpr function or a non-template, non-defaulted, non-inheriting constexpr constructor, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression (5.19), the program is ill-formed; no diagnostic required. [...]

È impossibile nel caso generale di rilevare in modo affidabile se esiste un'invocazione di funzione che consente di utilizzare il risultato in un'espressione costante, motivo per cui la diagnostica è facoltativa.

+0

Sono umiliato! :) – SergeyA

+1

Per inciso, la mancanza del supporto di 'constexpr' da lambdas è un po 'una caratteristica mancante in C++. [Qui] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4487.pdf) è una proposta del genere. – Yakk

Problemi correlati