Search code examples
c++templatesc++14language-lawyerpartial-specialization

Partial template specialization with mismatching `int` and `size_t` not compiling


With reference to the following code

#include <utility>
#include <cassert>

template <typename T>
struct Wot;
template <int... ints>
struct Wot<std::index_sequence<ints...>> {};

int main() {
    assert(sizeof(Wot<std::index_sequence<1, 2, 3>>) == 1);
}

This works on clang but does not work on gcc, when I change the type of the partial specialization to accept std::size_t in the index sequence however it works.

Who is right? Clang or gcc?


See this in action here https://wandbox.org/permlink/5YkuimK1pH3aKJT4


Solution

  • gcc is right. This is exactly [temp.deduct.type]/18:

    If P has a form that contains <i>, and if the type of i differs from the type of the corresponding template parameter of the template named by the enclosing simple-template-id, deduction fails. If P has a form that contains [i], and if the type of i is not an integral type, deduction fails. [ Example:

    template<int i> class A { /* ... */ };
    template<short s> void f(A<s>);
    void k1() {
      A<1> a;
      f(a);             // error: deduction fails for conversion from int to short
      f<1>(a);          // OK
    }
    
    template<const short cs> class B { };
    template<short s> void g(B<s>);
    void k2() {
      B<1> b;
      g(b);             // OK: cv-qualifiers are ignored on template parameter types
    }
    

    — end example ]

    Mirroring the example and simplifying the original question:

    template <class T> struct Wot { };
    
    template <int... ints>
    void foo(Wot<std::index_sequence<ints...>> ) { }
    
    int main() {
        foo(Wot<std::index_sequence<1, 2, 3>>{}); // error
        foo<1, 2, 3>({}); // ok
    }
    

    I think this is clang bug 16279