Mehrdeutigkeit bei Variadic-Template-Überladung
-
Hallo,
folgender Code kompiliert mit GCC 6.3.0 aber nicht mit Clang 3.9.1. Welcher Compiler hat Recht?
#include <iostream> template< typename... T > struct typelist { }; template< int v > struct int_ { }; template< int head, int... tail > std::ostream& operator<<( std::ostream& stream, typelist< int_< head >, int_< tail >... > ) { return stream << head << ' ' << typelist< int_< tail >... >{}; } template< int head > std::ostream& operator<<( std::ostream& stream, typelist< int_< head > > ) { return stream << head; } int main() { std::cout << typelist< int_< 1 >, int_< 2 > >{} << '\n'; }
Ausgabe von Clang:
main.cxx:13:31: error: use of overloaded operator '<<' is ambiguous (with operand types 'basic_ostream<char, std::char_traits<char> >' and 'typelist<int_<2> >') return stream << head << ' ' << typelist< int_< tail >... >{}; ~~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ main.cxx:21:12: note: in instantiation of function template specialization 'operator<<<1, 2>' requested here std::cout << typelist< int_< 1 >, int_< 2 > >{} << '\n'; ^ main.cxx:12:15: note: candidate function [with head = 2, tail = <>] std::ostream& operator<<( std::ostream& stream, typelist< int_< head >, int_< tail >... > ) { ^ main.cxx:16:15: note: candidate function [with head = 2] std::ostream& operator<<( std::ostream& stream, typelist< int_< head > > ) { ^ 1 error generated.
LG
-
Unter Visual Studio 2015 kompiliert der Code auch
Welcher Compiler nach Standard recht hat, kann ich grade nicht beurteilen.
-
Bump.
-
Ich empfehle, den Code zu minimieren, damit die Problematik schneller klar wird, etwa
template <int... I> struct list {}; template <int I, int... J> void f(list<I, J...>) {} template <int I> void f(list<I>) {} int main() { f(list<1>{}); }
Das scheint ein Bug in clang (in 4.0.0 immer noch vorhanden) zu sein.
clang hat keine Probleme mit
template <int... I> struct list {}; template <typename T> struct foo; template <int I, int... J> struct foo<list<I,J...>> {}; template <int I> struct foo<list<I>> {}; int main() { foo<list<1>> x; }
was mindestens inkonsequent ist.