C++ Templates: Partial Template Specialization

Share the Article

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:

compiler error due to usage of missing function in partial C++ template

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.

Main Funda: Partial template specialization takes responsibility to handle a subset of scenarios

Related Topics:

 What are the drawbacks of using enum ?
Which member functions are generated by compiler in class?
How to stop compiler from generating special member functions?
Compiler Generated Destructor is always non-virtual
How to make a class object un-copyable?
Explaining C++ casts
How pointer to class members are different ?
How std::forward( ) works?
Rule of Three
How std::move() function works?
What is reference collapsing?
How delete keyword can be used to filter polymorphism
Copy Constructor and Move Constructor: Test with vector


Share the Article

Leave a Reply

Your email address will not be published. Required fields are marked *