I have a trait to return some information about a class e.g. the number of dimensions:
template< typename T >
struct NumDims;
For a "normal" class this is easy to specialize:
template<>
struct NumDims< MyClass >: std::integral_constant< unsigned, 3 >{};
But I have some heavy templated classes that all have a common static constexpr like:
template< class T, class U, class V, bool x, bool y, bool z >
struct TemplateClass{
static constexpr unsigned numDims = ...;
}
A specilization looks ugly and errorprone:
template< class T, class U, class V, bool x, bool y, bool z >
struct NumDims< TemplateClass<T,U,V,x,y,z> >{
static constexpr unsigned value = TemplateClass<T,U,V,x,y,z>::numDims;
}
I tried to use variadic templates:
template< class... T >
struct NumDims< TemplateClass<T...> >{
static constexpr unsigned value = TemplateClass<T...>::numDims;
}
But this crashes my compiler (gcc 4.8.2):
internal compiler error: in unify_one_argument, at cp/pt.c:15506
Any ideas to do this "the prober" way?
Your issue is that you have a mixture of type and non-type parameters in your
TemplateClass
class template, so you can't have a variadic type parameter. As far as I know, there is currently no way to mix type and non-type arguments like that, short of wrapping the non-type ones in some dummy template.Fortunately, you can side-step the whole issue and just have a partial specialization which is enabled when the type you pass in has a
numDims
static member:This uses
void_t
which is not yet standard, so you can use a simple implementation like this: