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.


  • Mod

    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.


Anmelden zum Antworten