2015-03-17 9 views
20

Questo è un punto su cui gcc 4.9.2 e clang 3.5.2 sono in netto disaccordo . Il programma:Gli argomenti della funzione del pacchetto parametri possono essere impostati in modo predefinito?

template<typename ...Ts> 
int foo(int i = 0, Ts &&... args) 
{ 
    return i + sizeof...(Ts); 
} 

int main() 
{ 
    return foo(); 
} 

compila senza commento da gcc (-std=c++11 -Wall -pedantic). Clang dice:

error: missing default argument on parameter 'args' 

Con foo modificato a:

template<typename ...Ts> 
int foo(int i = 0, Ts &&... args = 0) 
{ 
    return i + sizeof...(Ts); 
} 

clang ha nessuna lamentela, ma gcc dice:

error: parameter pack ‘args’ cannot have a default argument 

quale compilatore è giusto?

+1

Si potrebbe lavorare intorno ad esso da sovraccarico: 'template int foo (int i, Ts && ...) {return i + sizeof ... (Ts); } inline int foo() {return foo (0); } ' – Oktalist

risposta

15

Da 8.3.6 ([dcl.fct.default])/3:

Un argomento di default non sono determinati per un pacchetto di parametri.

Da 8.3.6 ([dcl.fct.default])/4:

In una data dichiarazione di funzione, ogni parametro successivo ad un parametro con un argomento predefinito deve avere un argomento di default fornita in questa o in una precedente dichiarazione o deve essere un pacchetto di parametri di funzione.

Quindi questo consente il codice come void f(int a = 10, Args ... args), o effettivamente come il tuo primo frammento di codice. (Grazie a @ T.C. Per cercare la seconda frase!)

+3

Drat! ( –

+3

[dcl.fct.default]/4 ("In una dichiarazione di funzione data, ogni parametro successivo a un parametro con un argomento predefinito deve avere un argomento predefinito fornito in questo o in un precedente dichiarazione o sarà un pacchetto di parametri funzione ") sembrerebbe consentire la prima versione –

+0

@KerrekSB Sì, quindi consente la versione accettata da GCC. –

1

Un Kerrek SB dice, non è possibile. Che cosa si potrebbe fare, invece, utilizza un std::tuple

template <class ... Args> 
void foo(std::tuple<Args...> t = std::tuple<int>(0)) 
{}