I know there are a lot of posts about "Explicit specialization in non-namespace scope"; I already read most of them but (unless I didn't understand the answers well) they don't answer this specific question. As a matter of fact, I found a workaround in my program, but I'm interested to know the "real solution" to this problem if there is one.
The problem
Please bear with me, it's difficult to put into words. I have a template class A<typename T, unsigned n>
. I want to define a type-checker as a template inner struct is_A<typename U>
which checks if U
is some A
. This struct inherits from std::false_type
as is, and I specialize it to derive from std::true_type
for template types A<U,n>
.
Why do I want to do this? Because I want to define a template method A::method<U>
that behaves differently when U
is some A
or otherwise.
What worked
- Putting the non-specialized definition of
is_a<U>
before the declaration ofA
. And put the specialized version afterwards with 2 template arguments instead of 1; ietemplate <> template <typename T, unsigned n> struct is_A< A<T,n> > : std::true_type {};
. Why not, but I don't like so much adding a template argument, and exploding the definition ofis_A
is not so pretty either... - Removing
is_A
and using another type-checker formethod
which caracterizes precisely the type I expect (ie, whitelist approach instead of blacklist).
Is there another way than these workarounds which allows to write something similar to the following header?
The code
Here is the smallest header I could write to reproduce the error:
#ifndef __EXAMPLE__
#define __EXAMPLE__
#include <type_traits>
namespace name
{
template <typename T, unsigned n>
class A
{
public:
/**
* Type checkers
*/
template <typename U>
struct is_A : public std::false_type {};
template <> template <typename U>
struct is_A< A<U,n> > : public std::true_type {};
/**
* Specialized method
*/
// Version taking input of type A<U,n>
template <typename U>
void method( const A<U,n>& other ) {}
// Version taking inputs of other types
template <typename U,
typename = typename std::enable_if< !is_A<U>::value >::type >
void method( const U& x ) {}
};
}
#endif
Here is the error I get when I compile a cpp file including this header:
.h:21:12: error: explicit specialization in non-namespace scope 'class name::A<T, n>'
.h:30:7: error: too many template-parameter-lists
.h:35:7: error: too many template-parameter-lists