Skip to content
Theory · Templates · lesson 5 of 11

Class templates and specialization

The cookie cutter from the first lesson works for classes too: a whole struct can be written as a template. And if one dough needs a special shape, it gets a cutter of its own: that is a specialization.

A struct that holds one value and prints it looks the same for int, double and bool. Only the type of the field changes. Such a class is also written as a template, and the type goes in angle brackets when an object is created:

C++
#include <iostream>

template <typename T>
struct Box {
    T value;
    void print() const { std::cout << value << '\n'; }
};

int main() {
    Box<int> a{42};
    Box<bool> f{true};
    a.print();  // 42
    f.print();  // 1
}

Class template

A class template works like a function template. template <typename T> stands before struct or class, and T replaces the type in fields and methods. The template written for any T is called the primary template. Box<int> is an ordinary class that the compiler creates by substituting int for T. Box<int> and Box<bool> are different types, and an object of one cannot be assigned to a variable of the other.

Box has no constructor, and its field is public. So the values of the fields can be listed in curly braces in the order they are declared: Box<int> a{42};.

Class templates have already appeared in the course: std::vector<int> is the template std::vector with the argument int.

Full specialization

For bool, the primary template prints 1 where true is needed. A template can be given a separate version for one specific type, a full specialization:

C++
template <>
struct Box<bool> {
    bool value;
    void print() const { std::cout << (value ? "true" : "false") << '\n'; }
};

The empty angle brackets in template <> mean that no parameters are left: the type is already given in Box<bool>. The specialization is written after the primary template, and with it f.print() prints true.

Which version is chosen

Box<bool> could also be built from the primary template with T = bool. But this type has a full specialization, and the compiler takes it instead of the primary template. A specialization fits only its own type: unlike in overload resolution, promotions and conversions play no part here. That is why Box<int> is built from the primary template, even though int converts to bool.

Common mistake

The specialization keeps only the method that needs to change:

C++
template <>
struct Box<bool> {
    void print() const { std::cout << (value ? "true" : "false") << '\n'; }  // ✗
};
TEXT
error: use of undeclared identifier 'value'

This is a compiler error. A specialization is a separate class: it gets no fields or methods from the primary template. Declare everything it needs in it, the field value included.

Key points

  • A class template writes the class once, and Box<int> and Box<bool> are two different types.
  • The full specialization template <> struct Box<bool> is a separate version for one type.
  • A specialization is chosen only for exactly its own type, with no promotions or conversions.
  • A specialization inherits nothing from the primary template: fields and methods are declared again.

Subscribe to take the course

The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.

Sign in another way