2015-08-15 8 views
14
#include <tuple> 

template<int I> 
struct A {}; 

template<int I, typename... T> 
void f(A<I>, std::tuple<T *...>) {} 

template<typename... T> 
void f(A<0>, std::tuple<T *...>) {} 

int main() 
{ 
    f(A<0>{}, std::tuple<char*, int*, float*>{}); 
} 

Ist die zweite Überlast von f nicht spezialisierter? g ++ 4.9.2 sagt, dass der Aufruf mehrdeutig ist, clang 3.6.0 akzeptiert ihn. Welcher Compiler hat Recht?Ist nicht `void f (A <0>, Tupel <T *...>)` spezialisierter als `void f (A <I>, Tupel <T *...>)`?

Es ist interessant, dass, wenn Sie std::tuple<T *...> zu std::tuple<T...> ändern, g ++ in Ordnung ist, was ich nicht verstehe.

+0

MSVC 2013 ist auch damit zufrieden :) –

+0

Ich vermute, gcc ist falsch, aber es könnte etwas obskuren Wert Parameter-Parameter (der Standard neigt dazu, um sie herum schrulligen). Können Sie Repo ohne Verwendung von Werten? – Yakk

+0

[clang] (http://clang.llvm.org) ist auch OK mit dem Code. –

Antwort

5

Nach den aktuellen Regeln ist die zweite Überlast spezialisierter. Einige Spezialisierungen A<@> mit einem synthetisierten Wert @ können nicht mit A<0> verglichen werden, aber A<0> kann mit A<I> verglichen werden (mit I=0). Die Asymmetrie dieses ersten Paares ist entscheidend. Ob Sie als Muster im zweiten Parameter T oder T* verwenden, ist irrelevant, da der Abzug für dieses Paar auf beide Arten erfolgreich ist.

Der Fehler weiterhin im Stamm und wurde von @Barry als 67228 gemeldet.

+0

Hinweis: Die Auflösung CWG 1391 könnte dies mehrdeutig machen. Ich bin mir allerdings nicht sicher. – Columbo

+0

Ja, die Auflösung ist nicht ganz richtig, denke ich. Schauen Sie sich bogdans Antwort [hier] an (http://stackoverflow.com/a/31735126/2069064), ich denke, er hat einige gute Ideen, wie man die Formulierungen tatsächlich lösen kann. – Barry

+3

Ich habe [67228] (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67228) eingereicht. – Barry