Partial template specialization means, rewriting C++ templates by explicitly specifying a few but not all of the template parameters. Now, when such specializations are available, the compiler shall call these specialized template version on argument match only. Specifically, it no longer calls the main template. This is also a form of compile-time polymorphism.
The following program shows this:
#include <iostream> //main header
using namespace std; //namespace
//Main Template.
template<typename TT1, typename TT2> //Two types
class TestHash
{
TT1 key;
TT2 value;
public:
TestHash()
{
cout << "Main Template Constructor" << endl;
}
};
//Partial Template Specialization.
template<typename TT2> //Note : only one type
class TestHash<int, TT2>
{
int key;
TT2 value;
public:
TestHash()
{
cout << "Partial Specialization Constructor" << endl;
}
};
//Full Specialization.
template<> //Note : no type needed
class TestHash<int, float>
{
int key;
float value;
public:
TestHash()
{
cout << "Full Specialization Constructor" << endl;
}
};
int main()
{
TestHash<char, std::string> th1;
TestHash<int, std::string> th2;
TestHash<int, float> th3;
return 0;
}
The output of above program is:
Main Template Constructor
Partial Specialization Constructor
Full Specialization Constructor
Here, initialization of TestHash with “th2” calls the Partial Specialization, because the first template parameter “int” has a perfect match.
Missing Functions in Specialization
In any member function is missing in template specialization (either partial or full), then an object based on specialization will not be able call. However, objects based on main template will be able to call. In following code, the same class “TestHash” has a function “printStatus” missing in specialization.
#include <iostream> //main header
using namespace std; //namespace
template<typename TT1, typename TT2>
class TestHash
{
TT1 key;
TT2 value;
public:
TestHash()
{
cout << "Main Template Constructor" << endl;
}
void printStatus() //this is available only here
{
cout << "This is main template" << endl;
}
};
template<typename TT2>
class TestHash<int, TT2>
{
int key;
TT2 value;
public:
TestHash()
{
cout << "Partial Template Constructor" << endl;
}
};
int main()
{
TestHash<char, std::string> th1;
TestHash<int, std::string> th2;
th1.printStatus();
//th2.printStatus(); //This will generate error
return 0;
}
Output:
Main Template Constructor
Partial Template Constructor
This is main template
On uncommenting the “h2.printStatus()” line, the compiler will produce following error:
Uses of Partial Template Specialization
The implementation of std c++ functions which differentiate between types is generally done by using partial specialization.
For instance,
- std::is_reference,
- std::is_lvalue_reference,
- std::is_rvalue_reference,
- std::is_pointer
These are using this c++ feature to achieve the desired goal indeed.
Basic implementation for “is_pointer”
template<typename T>
class is_this_pointer
{
public:
enum { type=0 };
};
template<typename T>
class is_this_pointer<T*>
//Partial Specialization, T is type
{
public:
enum { type=1 };
};
Example with datatypes
The following code snippet uses the above implementation directly passing type
cout << "int : " << is_this_pointer<int>::type << endl;
cout << "int* : " << is_this_pointer<int*>::type << endl;
cout << "int**: " << is_this_pointer<int**>::type << endl;
The output is:
int : 0
int* : 1
int**: 1
Example with pointers:
int const *pp = 0;
int const **pq = &pp;
int const *pr = px;
cout<<"decltype(pp):"<<is_this_pointer<decltype(pp)>::type<< endl;
cout<<"decltype(pq):"<<is_this_pointer<decltype(pq)>::type<< endl;
cout<<"decltype(pr):"<<is_this_pointer<decltype(pr)>::type<< endl;
The output is:
decltype(pp) : 1
decltype(pq) : 1
decltype(pr) : 1
Example with variables (not pointers)
int ia;
int &ib=ia;
int &&ic=9;
cout<<"decltype(ia) :"
<< is_this_pointer<decltype(ia)>::type
<< endl;
cout<<"decltype(ib) :"
<< is_this_pointer<decltype(ib)>::type
<< endl;
cout<<"decltype(ic) :"
<< is_this_pointer<decltype(ic)>::type
<< endl;
The output is:
decltype(ia) :0
decltype(ib) :0
decltype(ic) :0
Partial Specialization for function templates
In particular, C++ do not allow partial specialization for function templates. Instead, the program should use function overloading to use the right implementation.