Template Specialization

Contents[Show]

Templates define the behavior of families of classes or functions. Often it is required that special types or non-types may be treated special. To support this use case, you can specialize templates.

 TemplateSpecialization

Let me start this post with the general idea of template specialization. In the next post, I concentrate on the details.

Template Specialization

Templates define the behavior of families of classes and functions. Often it is required that special types or non-types must be treated special. Therefore, you can fully specialize templates.

Class templates can also be partially specialized. The general or primary template can coexist with partially or fully specialized templates. The member functions and attributes of a specialization don’t have to be identical with those of the primary template. The compiler prefers fully specialized to partially specialized templates, and partially specialized templates to primary templates.

The following example should clarify my words.

template <typename T, int Line, int Column>     // (1)
class Matrix;

template <typename T>                           // (2)
class Matrix<T, 3, 3>{};

template <>                                     // (3)
class Matrix<int, 3, 3>{};

 

  • Primary Template

Line 1 is the primary or general template. The primary template has to be declared before the partially or fully specialized templates. If the primary template is not needed, a declaration such as in line 1 is fine.

  • Partial Specialization

Line 2 follows with the partial specialization. Only class templates support partial specialization. A partial specialization has template parameters and explicitly specified template arguments. In the concrete case, class Matrix<T, 3, 3> T is the template parameter and the numbers are the template arguments.

  • Full Specialization

 Line 3 is the full specialization. Full means that all template arguments are specified and the template parameter list is empty: template <> in line 3.

Partial versus Full Specialization

To better understand partial and full specialization, I want to present a visual explanation. You may know, I studied mathematic and I had many linear systems of equations to solve.

Think about an n-dimensional space of template parameters. A partial specialization is a subspace in the n-dimensional space, and a full specialization is a point in the n-dimensional space.

Now, I apply my visual explanation to the class template Matrix and its partial and full specialization. In the primary template (line 1) you can choose a type as a template parameter, and two int values as non-type template parameter. In the case of the partial specialization in line 2, you can only choose the type. This means the 3-dimensional space is reduced to a line. The partial specialization of the primary template Matrix is, therefore, a subspace of the 3-dimensional space. The full specialization (line 3) stands for a point in the 3-dimensional space. 

What is happening when you invoke the templates?

Using the Primary, Partial, and Full Specialization

To remind you, the following specializations of the class Matrix are given.

template <typename T, int Line, int Column>     // (1)
class Matrix;

template <typename T>                           // (2)
class Matrix<T, 3, 3>{};

template <>                                     // (3)
class Matrix<int, 3, 3>{};

 

The question is: What happens when you instantiate Matrix for various template arguments? Here are three instantiations, and you see what the compiler creates.

 

Matrix<int, 3, 3> m1;          // class Matrix<int, 3, 3>

Matrix<double, 3, 3> m2;       // class Matrix<T, 3, 3> 

Matrix<std::string, 4, 3> m3;  // class Matrix<T, Line, Column> => ERROR

 

m1 uses the full specialization, m2 uses the partial specialization, and m3 the primary template which causes an error because the definition is missing.

To understand this process, you have to keep a few rules in mind. Here are the rules that apply, in particular, to the partial specialization of class templates.

Dependencies between the Template Parameter and the Template Arguments

  • The number and sequence of the explicitly specified template arguments (<T, 3, 3>) must match the number and sequence of the template parameter list (<typename T, int Line, int Column>) of the primary template.
  • If you use defaults for template parameters, you don't have to provide the template arguments. Only the primary template accepts defaults for template parameters.

Valid Partial Specializations

  • The compiler chooses a partial specialization if the template instantiation arguments (Matrix<double, 3, 3>) are a subset of the template arguments of the partial specialization (Matrix<T, 3, 3>).

Chosen Template Specialization

  1. The compiler finds only one specialization. The compiler uses this specialization.
  2. The compiler finds more than one specialization. The compiler uses the most specialized one. If this process ends in more than one specialization, the compiler throws an error.
  3. The compiler finds no specialization. It uses the primary specialization.

Okay, there is one question left I have to answer. What does it mean that a template A is a more specialized template than another template B. This is my informal definition.

A template A is more specialized than a template B:

  • The template B can accept all arguments that template A can accept.
  • The template B can accept arguments that template A cannot accept.

If you want to have it more formal, visit cppreference.com/partial_specialization and go to the subsection about partial ordering.

What's next?

This post should provide you the basics about template specialization but as always there are more details to it in C++. For example, partial or full specialization behaves like a compile-time if and full specialization of class or function templates are quite similar to ordinary classes or functions.

Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, Marko, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Animus24, Jozo Leko, John Breland, espkk, Louis St-Amour, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Neil Wang, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Tobi Heideman, Daniel Hufschläger, Red Trip, Alexander Schwarz, Tornike Porchxidze, Alessandro Pezzato, Evangelos Denaxas, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Satish Vangipuram, and Michael Dunsky.

 

Thanks in particular to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, and Said Mert Turkal.

 

 

My special thanks to Embarcadero CBUIDER STUDIO FINAL ICONS 1024 Small

 

Seminars

I'm happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.

Bookable (Online)

German

Standard Seminars (English/German)

Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.

New

Contact Me

Modernes C++,

RainerGrimmSmall

 

 

 

 

 

 

 

My Newest E-Books

Course: Modern C++ Concurrency in Practice

Course: C++ Standard Library including C++14 & C++17

Course: Embedded Programming with Modern C++

Course: Generic Programming (Templates)

Course: C++ Fundamentals for Professionals

Interactive Course: The All-in-One Guide to C++20

Subscribe to the newsletter (+ pdf bundle)

Blog archive

Source Code

Visitors

Today 7172

Yesterday 7224

Week 29171

Month 34436

All 6892645

Currently are 165 guests and no members online

Kubik-Rubik Joomla! Extensions

Latest comments