user42768
user42768

Reputation: 1971

C++ explicit specialization of member template belonging to template class

In the current C++ standard draft, there is this example in this paragraph belonging to the section related to explicit specialization of templates:

template<class T> struct A {
   void f(T);
   template<class X1> void g1(T, X1);
   template<class X2> void g2(T, X2);
   void h(T) { }
};

// specialization
template<> void A<int>::f(int);

// out of class member template definition
template<class T> template<class X1> void A<T>::g1(T, X1) { }


// member template specialization
template<> template<class X1> void A<int>::g1(int, X1);  //(1)

// member template specialization
template<> template<>
void A<int>::g1(int, char);                              //(2)

In (1) it seems more like g1 was specialized to be still a function template in the specialized version of A (A< int >), while in (2) it seems like g1 is itself specialized for its own set template parameters ( (int, from A< int >), char).

I find there to be a difference between these specializations (again, (1) feels like declaring a new version of g1 to be used for a "special version" of its "container" A, while (2) feels like a specialization regarding g1 itself (or regarding its own template parameters).

Furthermore, consider this example:

template<class T> struct A{
   int f() { return 1; }
}

template<>
int A<int>::f() { return 2; }                            //(3)

To me (1) and (3) are the same "kind of specialization", one that is linked to a special version of the "container", while (2) is a specialization of the entity (template) itself.

Does the standard mention this difference or are these two kinds of specialization referred to as the same?

Thank you.

Upvotes: 4

Views: 458

Answers (1)

Davis Herring
Davis Herring

Reputation: 40053

First, your #3 is equivalent to the first specialization in the cited example, except that the standard’s f uses the class’s template parameter in its signature—presumably to illustrate that, since the signature must match for a specialization, template arguments for the class may need to be repeated in the specialization declaration.

Then, the difference is that #1 is a specialization of a member of A<T> when T is int—a sort of shorthand for writing a specialization of A<int> itself that is mostly the same as the primary template. In particular, to avoid being misleading, the signature for the member being specialized must be unchanged from the (instantiation of the) primary template. In this case, that means it’s still a template.

On the other hand, #2 is a specialization of a template that happens to be a member of A<int>—the specialization is of A<int>::g1 itself, not of “A<T>::g1 when T is int” as for #1. This of course applies only when the member is a template, unlike #3. (In this case, #2 is a specialization of the very template declared by #1!)

Part of the point of [temp.expl.spec]/15 is that these two cases are not strongly distinguished syntactically. The difference is largely academic: both are surgical changes to a templated entity for certain arguments.

Upvotes: 1

Related Questions