C++ template class, types, and simple tricks
A template class lets you write one class pattern and let the compiler create real classes from it for the types you use.
Without templates, you may write the same class many times:
Both classes have the same idea. Only the stored type is different.
With a template class, write the idea once:
Output:
What the syntax means
This means Box is not one finished class yet. It is a class template.
T is a type parameter. It is a placeholder for a real type such as:
intdoublestd::string- your own class type
Inside the class, T is used like a normal type:
When the code uses:
the compiler replaces T with int.
When the code uses:
the compiler replaces T with std::string.
What the compiler does
The compiler does not compile Box<T> as one normal class.
It waits until it sees which types are used, then it generates real classes from the template.
For this code:
the compiler acts like it created two separate classes.
Conceptually, it creates something like this for Box<int>:
And something like this for Box<std::string>:
These names are only for explanation. The compiler uses its own internal names.
This process is called template instantiation.
Each type gets its own class
Box<int> and Box<double> are different types.
This means this code does not compile:
Even though both come from the same template, the compiler treats them as different classes after instantiation.
Errors happen when the template is used
A template is checked fully only when the compiler creates a real class from it.
For example:
This works with int:
It also works with std::string:
But it fails for a type that does not support operator+:
The template code asks for value_ + value_. The compiler can only generate
that code for types where + is valid.
What types can a template use?
A template type parameter can use almost any C++ type.
Common examples:
- built-in types:
int,double,bool,char - standard library types:
std::string,std::vector<int> - pointer types:
int*,User* - reference types:
int&,const std::string& - your own classes and structs:
Robot,User,Point
Example:
The important rule is simple: the type must support the operations used inside the template.
If the template only stores and returns the value, many types work.
If the template uses +, the type must support +.
If the template uses <, the type must support <.
If the template prints with std::cout << value, the type must support
operator<<.
Template with multiple parameters
A template can have more than one type parameter.
Output:
Here the compiler creates one class for:
and another class for:
Each different combination of template arguments creates a different type.
Template with a non-type parameter
Templates can also receive values, not only types.
This is called a non-type template parameter.
Array<int, 3> and Array<int, 5> are different types because the size is part
of the template arguments.
Simple template tricks and usages
Use a template for a reusable function
Templates are not only for classes. A common use is a function that works with different types.
Usage:
In many cases, the compiler can detect the type automatically:
This is called template argument deduction.
Use using to make a template easier to read
Long template names can become noisy.
Now the usage is shorter:
IntBox is only an alias. The real type is still Box<int>.
Give a template a default type
A template parameter can have a default value.
Usage:
The empty <> means: use the default template argument.
Use static_assert for a clear compile error
Sometimes a template should only accept certain kinds of types.
For example, this class should only work with numbers:
This works:
This fails with a clear error:
static_assert is useful because it tells the user of the template what the
rule is.
Important idea
A template class is a recipe.
Box<T> is the recipe.
Box<int> is a real class generated from the recipe.
Box<std::string> is another real class generated from the same recipe.
The compiler creates only the versions that your program actually uses.