2

I'm not sure I'm getting the terminology correct, but I think I have a class template with both a type and non-type template parameter and I want to partially specialize on the non-type parameter alone:

template<class T, int I> struct A
{
    void f();
};

template<class T> void A<T, 1>::f() {}

int main()
{
    A<int, 1> a1;
    a1.f();
}

Using Visual C++ I get error C3860: template argument list following class template name must list parameters in the order used in template parameter list and error C2976: 'A<T,I>': too few template arguments.

However if I remove the type parameter then it seems I can specialize on the non-type parameter:

template<int I> struct B
{
    void g();
};

void B<1>::g() {}

int main()
{
    B<1> b1;
    b1.g();
}

So is what I want impossible, or I'm just not doing it the right way? If it's not possible, is there an alternative?

George Skelton
  • 1,095
  • 1
  • 10
  • 22
  • 1
    See [this question](http://stackoverflow.com/questions/10284498/partial-specialization-of-a-method-in-a-templated-class). The fact that your template parameter is not a type is a red herring. The reason the second example works is because it's a full specialization. – François Andrieux Jan 10 '17 at 16:57
  • Possible duplicate of [Partial specialization of a method in a templated class](http://stackoverflow.com/questions/10284498/partial-specialization-of-a-method-in-a-templated-class) – realvictorprm Jan 10 '17 at 16:59

1 Answers1

2

Let's consider what the standard (working draft) says:

A member [...] of a class template may be explicitly specialized for a given implicit instantiation of the class template, even if the member [...] is defined in the class template definition. An explicit specialization of a member [...] is specified using the syntax for explicit specialization.

In other terms, what you are trying to do is not allowed.
That's all.


Imagine if it was, hipotetically you would have been allowed also to do this:

template<class T, int>
struct A { void f(); };

template<typename T>
void A<T, 1>::f() {}

template<>
struct A<int, 1> {};

That is, define f for a class template a specialization of which could not even have a declaration for f.
It doesn't make much sense, does it?

On the other side, consider the following member specialization:

template<>
void A<int, 1>::f() {}

It causes an instantiation of A<int, 1> that cannot be further specialized.
In other terms, you cannot do this in this case:

template<>
struct A<int, 1> {};

The presence of f is somehow guaranteed thus.

skypjack
  • 49,335
  • 19
  • 95
  • 187
  • Thanks this makes sense. I had shied away from partial specialization of the whole class because of the need to repeat so much code (in reality it's a big class). But I see now it has to work this way. – George Skelton Jan 11 '17 at 13:33