Question

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

  1. Putting the non-specialized definition of is_a<U> before the declaration of A. And put the specialized version afterwards with 2 template arguments instead of 1; ie template <> 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 of is_A is not so pretty either...
  2. Removing is_A and using another type-checker for method 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
Was it helpful?

Solution

It seems to work for me if you do as the compiler advises: Leave out the template<>:

template <typename U>
struct is_A< A<U,n> > : public std::true_type {};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top