Maybe I'm tired, but I'm stuck with this simple partial specialization, which doesn't work because non-type template argument specializes a template parameter with dependent type 'T'
:
template <typename T, T N> struct X; template <typename T> struct X <T, 0>;
Replacing 0
by T(0)
, T{0}
or (T)0
doesn't help. So is this specialization even possible?
Which parameter is legal for non-type template? Explanation: The following are legal for non-type template parameters:integral or enumeration type, Pointer to object or pointer to function, Reference to object or reference to function, Pointer to member.
A non-type template argument provided within a template argument list is an expression whose value can be determined at compile time. Such arguments must be constant expressions, addresses of functions or objects with external linkage, or addresses of static class members.
For example, given a specialization Stack<int>, “int” is a template argument. Instantiation: This is when the compiler generates a regular class, method, or function by substituting each of the template's parameters with a concrete type.
A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.
See paragraph [temp.class.spec] 14.5.5/8 of the standard:
The type of a template parameter corresponding to a specialized non-type argument shall not be dependent on a parameter of the specialization. [ Example:
template <class T, T t> struct C {}; template <class T> struct C<T, 1>; // error template< int X, int (*array_ptr)[X] > class A {}; int array[5]; template< int X > class A<X,&array> { }; // error
—end example ]
The answer to your edit: the easiest workaround is to replace a non-type template parameter with a type one:
#include <type_traits> template <typename T, typename U> struct X_; template <typename T, T N> struct X_<T, std::integral_constant<T, N>> {}; template <typename T> struct X_<T, std::integral_constant<T, 0>> {}; template <typename T, T N> struct X : X_<T, std::integral_constant<T, N>> {};
Solution using Yakk's solution:
#include <iostream> #include <type_traits> template <typename T, T N, typename = void > struct X { static const bool isZero = false; }; template <typename T, T N> struct X < T, N, typename std::enable_if<N == 0>::type > { static const bool isZero = true; }; int main(int argc, char* argv[]) { std::cout << X <int, 0>::isZero << std::endl; std::cout << X <int, 1>::isZero << std::endl; return 0; }
Live Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With