Introduction
C++ Templates are a powerful feature that allows you to write generic code by parameterizing types. They not only generalize functions and classes but also dramatically improve the expressiveness of C++, enabling handling of variable-length arguments and defining special processing for specific types.
In this article, I will comprehensively explain everything from the basic usage of templates to more advanced and practical topics like variadic arguments and specialization.
1. Function Templates
Function templates allow you to define generic functions that are independent of types. The compiler automatically infers the actual type to be used based on the argument types.
Sample Code
template <typename T>
T get_max(T a, T b) {
return (a > b) ? a : b;
}
// Generic lambda (since C++14) is also a form of function template
auto add = [](auto a, auto b) {
return a + b;
};
Explanation: The get_max function works with any type (int, double, string, etc.) as long as the > operator is defined for it.
2. Class Templates
Class templates allow you to define generic classes independent of types. When using them, you generally need to explicitly specify the concrete type in < > (although type deduction is partially available since C++17).
Sample Code
template <typename T>
class Pair {
public:
T first, second;
};
int main() {
Pair<int> p_int; // Instantiate with T as int
p_int.first = 10;
// Class Template Argument Deduction (CTAD) (since C++17)
Pair p_double{3.14, 2.71}; // Automatically infers T is double
return 0;
}
3. Variadic Templates
Since C++11, it is possible to accept an arbitrary number of template arguments. This allows you to implement functions with a variable number of arguments, like printf, in a type-safe manner.
Sample Code
#include <iostream>
// Base function to stop recursion
void print_all() {
std::cout << std::endl;
}
// Recursive function using variadic templates
template <typename T, typename... Args>
void print_all(const T& first, const Args&... rest) {
std::cout << first << " ";
print_all(rest...); // Expand the remaining argument pack and call recursively
}
int main() {
print_all(1, "hello", 3.14); // Passing 3 arguments of different types
return 0;
}
4. Alias Templates
Since C++11, you can use using to give an alias to a template. This is very convenient for simplifying complex type names.
Sample Code
#include <vector>
#include <string>
#include <map>
// Give an alias StringMap<T> to std::map<std::string, T>
template <typename T>
using StringMap = std::map<std::string, T>;
int main() {
// Same meaning as std::map<std::string, int>
StringMap<int> user_scores;
user_scores["Taro"] = 100;
return 0;
}
5. Template Specialization
Use specialization when you want to provide a special implementation for a specific type that differs from the standard template implementation.
Sample Code
#include <iostream>
#include <vector>
// Generic Class Template
template <typename T>
class Container {
public:
void print() { std::cout << "Generic Template" << std::endl; }
};
// 1. "Full Specialization" when T is int
template <>
class Container<int> {
public:
void print() { std::cout << "Template Specialized for int" << std::endl; }
};
// 2. "Partial Specialization" when T is vector<U>
template <typename U>
class Container<std::vector<U>> {
public:
void print() { std::cout << "Template Partially Specialized for vector" << std::endl; }
};
int main() {
Container<double> c_double;
Container<int> c_int;
Container<std::vector<char>> c_vector;
c_double.print();
c_int.print();
c_vector.print();
return 0;
}
Explanation: Container calls a specific implementation depending on whether it is used with an int type or a vector type.
Summary
In this article, I comprehensively explained C++ templates, ranging from basic functions to advanced topics like variadic arguments and specialization.
Templates are a core feature supporting C++’s static polymorphism and generic programming, serving as the foundation for the STL (Standard Template Library). Understanding these features enables you to write highly reusable, type-safe, and efficient code.
