Search code examples
c++templatesc++11language-lawyertype-parameter

Partially specializing on non-type template parameter of the wrong type


Consider the following:

template <unsigned >
struct uint_ { };

template <class >
struct X {
    static constexpr bool value = false;
};

template <int I> // NB: int, not unsigned
struct X<uint_<I>> {
    static constexpr bool value = true;
};

int main() {
    static_assert(X<uint_<0>>::value, "!");
}

clang compiles the code, gcc does not.

However, in the following highly related example:

template <unsigned >
struct uint_ { };

template <int I> // NB: int, not unsigned
void foo(uint_<I> ) { }

int main() {
    foo(uint_<0>{} );
}

both compilers reject with no matching function call to foo. gcc's behavior is consistent, clang's is not - so one or the other compiler has a bug for one or both examples. Which compiler is correct?


Solution

  • GCC is correct. [temp.deduct.type]/17:

    If P has a form that contains <i>, and if the type of the corresponding value of A differs from the type of i, deduction fails.