2016-01-02 8 views
15

Il seguente programma viene compilato con GCC 5.2, ma non con clang 3.6:È questo messaggio di errore corretto: non-tipo di argomento modello non è un'espressione costante

constexpr bool flag(); 

template <bool b = flag()> 
constexpr bool test() 
{ 
    return b; 
} 

int main() 
{ 
} 

Il messaggio di errore che ottengo con clang è:

main.cpp:3:20: error: non-type template argument is not a constant expression 
template <bool b = flag()> 
        ^~~~~~ 
main.cpp:3:20: note: undefined function 'flag' cannot be used in a constant expression 
main.cpp:1:16: note: declared here 
constexpr bool flag(); 
      ^
main.cpp:4:16: error: no return statement in constexpr function 
constexpr bool test() 
      ^

La mia domanda è: chi ha ragione? O, in altre parole: il programma è mal formato?

+1

Può confermare questo, anche clang 3.7 non lo compila. Tuttavia, se inserisci un'istruzione return in 'constexpr bool flag()', funziona. – vsoftco

+1

Penso che questo si riferisca alla tua altra domanda sul punto in cui vengono valutati gli argomenti del template di default: Se sono valutati al punto di definizione, clang non può provare che questo modello è mal formato sotto [temp.res] p8 – dyp

+0

Perché hai una dichiarazione di ritorno in una funzione nulla? Posso anche confermare che questo compila su MSVS 2015 – NathanOliver

risposta

4

direi che clang ha ragione:

dallo standard:

[temp.param] 14,1 # 9

9 Un modello-argomento di default è un modello-argument (14.3) specificato dopo = in un parametro template. [...]

E [temp.arg.nontype] 14.3.2

1 Un modello-argomento per un non-tipo di modello-parametro deve essere un convertito un'espressione costante (5,20) del tipo del parametro-modello.

E [expr.const] 5,20

2 A condizionale espressione-e è un nucleo costante espressione meno che la valutazione di e, seguendo le regole della macchina astratta (1.9), sarebbe valutare uno delle seguenti espressioni:

[...]

(2.3) - un'invocazione di una funzione constexpr indefinita o un costruttore di constexpr indefinito;

Poiché flag() è dichiarato ma non definito, non è un'espressione costante e 14.3.2 è violato.

4

Secondo ISO C++ 14 standard 5.19.2:

A condizionale espressione-e è un nucleo espressione costante a meno che la valutazione di e, seguendo le regole della macchina astratta (1,9), sarebbe valutare una delle seguenti espressioni:

  • questo (5.1.1), se non in funzione constexpr o un costruttore constexpr che viene valutato come parte di e;
  • un'invocazione di una funzione diversa da un costruttore di constexpr per una classe letterale, una funzione constexpr o un'invocazione implicita di un distruttore banale (12.4) [Nota: la risoluzione di sovraccarico (13.3) viene applicata come di consueto - nota finale] ;
  • un'invocazione di una funzione constexpr non definita o un costruttore di constex non definito;
  • (...) Blockquote

Il risultato di ogni chiamata di funzione constexpr fatta prima di esso definizione non è un'espressione costante.

Infine sembra che sia un bug GCC.

+2

Penso che tutti siano d'accordo. Ci sono alcune domande aggiuntive, ma il principale è probabilmente: clang è autorizzato a rifiutare questo programma * anche se l'argomento del template predefinito non viene mai usato *? – dyp

+0

@ FilipRoséen-refp So che hai dovuto occuparti di questo per le tue tecniche di smeta, ma non riesco a ricordare da dove vengono queste informazioni. Proviene da una bozza, una discussione, un rapporto sui difetti, ..? – dyp

+0

@ dyp Sono abbastanza sicuro di indirizzare la particolare formulazione in uno dei post su http://b.atch.se - Sono attualmente in metropolitana ma posso fornire dettagli sull'argomento (inclusa una risposta) quando tornare a casa (si spera). –