Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

(Partially) specializing a non-type template parameter of dependent type

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?

like image 677
iavr Avatar asked Mar 18 '14 17:03

iavr


People also ask

Which parameter is allowed for non-type template?

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.

What is non-type parameter in template C++?

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.

Which is a correct example of template parameters?

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.

What is template type parameter?

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.


2 Answers

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>> {}; 
like image 131
Constructor Avatar answered Sep 23 '22 08:09

Constructor


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

like image 22
Sam Cristall Avatar answered Sep 19 '22 08:09

Sam Cristall