1
votes
#include <iostream>
using namespace std;

template<class T, int I>  // primary template
struct A {
    void f(); // member declaration
};
 
template<class T, int I>
void A<T,I>::f() { } // primary template member definition
 
// partial specialization
template<class T>
struct A<T,2> {
    void f();
    void g();
    void h();
};
 
// member of partial specialization
template<class T>
void A<T,2>::g() { 
    cout << "partial g()" << endl;
}

template<class T>
void A<T,2>::h() { 
    cout << "partial h()" << endl;
}
 
// explicit (full) specialization
// of a member of partial specialization
template<>
void A<char,2>::h() {
    cout << "explicit h()" << endl;
}
 
int main() {
    A<char,2> a2;
    a2.f(); // ERROR, partial can not access primary member
    a2.g(); // OK, uses partial specialization's member definition
    a2.h();  // OK, explicit h() being called.
}

I went thorugh cpp reference, It says

"Members of partial specializations are not related to the members of the primary template."

So understandably, a2 can not access member of primary specialization a2.f() ?

My Questions are

  1. how is the relationship between member of partial specialization and member of explicit specialization ?

  2. Why a2 can access the member of partial specialization a2.g() here ?

1
1) There is no relationship. 2) Because it's defined? P.S. a2.f(); is declared, but not defined, so the code compiles just fine, but fails to link due to undefined template member. - Sam Varshavchik
@Sam Thx. if there is no relationship, what is the cause that when we do a2.h(), the explicit one is called, not the one in the partial specialization ? - sthbuilder
Why shouldn't it? A<char,2>::f() is explicitly specialized, so it get's called. It is a member of class A<char, 2>. - Sam Varshavchik

1 Answers

1
votes

It is important to realize that a class template is not a class, but only a blueprint for one.

A<char,2> matches the specialized blueprint, so it has f,g,h member functions. Contents of the primary template are completely ignored.

Because A is a template class, its methods are instantiated only when actually called and only for those concrete template arguments because instantiation of A is a class, thus it has only one set of methods.

  • Since you did not define any A<char,2>::f, the linker reports undefined reference error.
  • There is a definition of A<char,2>::g available by instantiating template<class T> void A<T,2>::g() function - that is an ordinary method, not a function template.
  • For the same reason, A<char,2>::h also compiles - there is a definition for this function, nothing more is required.

In a nutshell, the compiler will only look for the definitions it needs, if it finds a matching template, it will generate the definitions. Otherwise it will mark the symbol as missing and it is your responsibility that the linker will have it available.