2014-12-04 8 views
10

Il codice di seguito lavora in gcc-4.8.2 Clang vs GCC - variadic parametro Template Pack seguito dal parametro con valore di default funziona in GCC 4.8, ma non clang 3,5

#include <iostream> 
using namespace std; 

template<typename... Args> 
void func(Args... args, int optional = 0) 
{ 
    cout << optional << endl; 
} 

int main() 
{ 
    func(1); 
    func(2.1f); // converts 2.1 to int as 'optional' parameter 
    func<float>(3.3f); // Fine, prints '0' 
    func(); // gcc OK, fails to compile with clang-3.5 
} 

Ed Uscite:

$ ./a.out 
1 
2 
0 
0 

Ma se non riesce a compilare con clang-3.5,

test_variadic.cpp:15:2: error: no matching function for call to 'func' 
    func(); 
    ^~~~ 
test_variadic.cpp:5:6: note: candidate function template not viable: requires at least argument 'args', but no arguments were provided 
void func(Args... args, int optional = 0) 
    ^

clang almeno avverte di la conversione implicita da un float a un int. Bene, possiamo correggerlo chiamando lo func<float> che inserisce il parametro float nel template pack. Quindi, se commento fuori func(), compila bene.

Non riesco a trovare nulla nel proverbio standard esplicitamente che il template pack variadic debba essere l'ultima cosa nella clausola-dichiarazione-parametro, solo che diventa un contesto non dedotto.

La mia confusione deriva dal motivo per cui clang non piace func() quando func(1) è perfettamente accettabile. Posso definire manualmente func(int optional = 4) { cout << optional << endl; } e tutto va bene (ma anziché la funzione templated quando passa int ho correttamente ottengo il specializzata func() sia clang e gcc. Qual è enforcing clang che limita l'uso di func()?

+3

[lavora per clang 3.5] (http://coliru.stacked-crooked.com/a/6d2184a139335a5b) –

+0

Ecco quale versione sto utilizzando, '$ clang --version Ubuntu versione clang 3.5-1ubuntu1 (tronco) (sulla base di LLVM 3.5) Obiettivo: x86_64-pc-linux-gnu ' e il comando 'clang ++ -std = c + +11 -O2 -Wall -pedantic test_variadic.cpp' – ilektron

+1

Interessante. La stessa riga di comando ma con la versione "Ubuntu clang version 3.5.0-svn217640-1 ~ exp1 (branches/release_35) (basata su LLVM 3.5.0)" compila solo con l'avviso. –

risposta

3

Questo in realtà è coperto dal leggermente Misplaced [temp.arg.explicit]/3:.

un parametro di modello finale pacco (14.5.3) non altrimenti deducibile sarà dedotta ad una sequenza vuota di argomenti template

Il pacchetto parametri template è in coda e quindi dedotto nel pacchetto vuoto in tutte le chiamate tranne per func<float>(3.3f), vale a dire, sono tutti validi (e Clang li compila bene as of 3.5).


Tuttavia, i compilatori non sono conformi più una volta registriamo la dichiarazione del modello per

template <typename... Args, typename=void> 
void func(Args... args, int optional = 0) 

Ora, la citazione di cui sopra non è applicabile (come Args non è in svantaggio) e [temp.deduct.call]/1 applica invece:

Quando un parametro funzione pack appare in un contesto non dedotta (14.8.2.5), il tipo di quel parametro confezione è neve dedotto.

(Ie questo dovrebbe produrre un fallimento deduzione.)

+0

Ti dispiacerebbe depositare un bug clang su http://llvm.org/bugs/enter_bug.cgi?product=clang – ismail

+0

@ilektron Ho modificato questa risposta a causa della discussione in [qui ] (https://llvm.org/bugs/show_bug.cgi?id=21774). – Columbo