2014-07-12 6 views
6

clang 3.4 accetta il seguente codice; mentre VC++ NOV 2013 CTP lo respinge con un errore:Perché il codice è accettato da clang ma respinto da vC++?

error C2668: 'AreEqual' : ambiguous call to overloaded function 
template<class headT, class... tailTypes> 
constexpr headT&& __GetFirst__(headT&& value, tailTypes&&...) 
{ 
    return static_cast<headT&&>(value); 
}; 

template<class T> 
constexpr bool AreEqual(const T& a, const T& b) 
{ 
    return a == b; 
} 

template<class headT, class... tailTypes> 
constexpr bool AreEqual(const headT& head_value, const tailTypes&... tail_values) 
{ 
    return AreEqual(head_value, __GetFirst__(tail_values...)) 
      && AreEqual(tail_values...); 
} 

int main() 
{ 
    AreEqual(1, 1, 2, 1); 
} 

quale compilatore è corretto secondo lo standard C++ 14?

Aggiornamento: Il messaggio di errore completo:

error C2668: 'AreEqual' : ambiguous call to overloaded function 
1>   d:\projects\ktl\test\main.cpp(20): could be 'bool AreEqual<headT,int>(const headT &,const int &)' 
1>   with 
1>   [ 
1>    headT=int 
1>   ] 
1>   d:\projects\ktl\test\main.cpp(8): or  'bool AreEqual<headT>(const T &,const T &)' 
1>   with 
1>   [ 
1>    headT=int 
1> ,   T=int 
1>   ] 
1>   while trying to match the argument list '(const int, const int)' 
1> 
1>Build FAILED. 
+4

Side : '__GetFirst__' è un nome riservato. –

+0

Puoi postare il messaggio di errore completo per favore? –

+0

non so quale sia corretto, ma la correzione facile sta avendo variadic prendere 3+ parametri – sp2danny

risposta

8

Clang (e GCC) 's comportamento è corretto. Si può leggere §14.8.2.4 [temp.deduct.partial] dello standard per come l'ordinamento parziale per i modelli di funzione è fatto, ma l'esempio dato in p8 di quel sottoclausola copre direttamente questa situazione: nota

template<class... Args> void f(Args... args); // #1 
template<class T1, class... Args> void f(T1 a1, Args... args); // #2 
template<class T1, class T2> void f(T1 a1, T2 a2); // #3 
f(); // calls #1 
f(1, 2, 3); // calls #2 
f(1, 2); // calls #3; non-variadic template #3 is more 
     // specialized than the variadic templates #1 and #2 
+2

+1. Inoltre è stato aggiunto l'identificatore '[parentesi quadre]' per quella sottoclausea per rendere più facile la ricerca in diverse versioni dello standard. (La specifica clausola #s si muove ma quegli identificatori sono fissi) –

+2

@BillyONeal Mi piacerebbe litigare su quegli identificatori che sono stati corretti ('basic.lookup.koenig'->' basic.lookup.argdep' :)) ma punto preso. –

+0

T.C. lol - beh, relativamente fissi in ogni caso –

Problemi correlati