Templates are a powerful feature of C++ that allow you to write generic and reusable code. A template lets you define a function or class without specifying the exact data type in advance.
A template is a blueprint for creating functions or classes that can work with different data types.
template <typename T>
T add(T a, T b) {
return a + b;
}
Here, T represents a type that will be provided when the
function is used.
Templates help reduce duplicate code.
Without templates, you may need separate functions for different data types.
int add(int a, int b);
double add(double a, double b);
A template can handle both types using one generic function.
template <typename T>
T add(T a, T b) {
return a + b;
}
A function template defines a generic function that can work with different data types.
template <typename T>
T maximum(T a, T b) {
return (a > b) ? a : b;
}
The same function can be used with integers, floating-point values, and other compatible types.
#include <iostream>
template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
std::cout <<
add(10, 20)
<< std::endl;
std::cout <<
add(2.5, 3.5);
return 0;
}
The compiler can generate suitable versions of the function for the types used in the calls.
The typename keyword is commonly used to declare a type
parameter in a template.
template <typename T>
void display(T value) {
std::cout << value;
}
Here, T is a placeholder for a data type.
The keyword class can also be used for a type parameter in
a template declaration.
template <class T>
T square(T value) {
return value * value;
}
For a type parameter, typename and class are
generally interchangeable in this context.
template <typename T>
void display(T value) {
std::cout <<
value
<< std::endl;
}
int main() {
display(10);
display(5.5);
display('A');
display("Hello");
return 0;
}
The template can work with different types as long as the operations used by the template are valid for those types.
A template can use more than one type parameter.
template <typename T, typename U>
void display(T first, U second) {
std::cout <<
first << " "
<< second;
}
Here, T and U can represent different types.
#include <iostream>
template <typename T, typename U>
void display(
T first,
U second
) {
std::cout <<
first << " "
<< second;
}
int main() {
display(
10,
5.5
);
return 0;
}
The first parameter can be an integer while the second parameter can be a floating-point value.
When a function template is called, the compiler can often determine the template type from the function arguments.
template <typename T>
T square(T value) {
return value * value;
}
int result = square(5);
double value = square(2.5);
The compiler deduces T from the argument.
You can explicitly specify a template type when needed.
template <typename T>
T add(T a, T b) {
return a + b;
}
double result =
add<double>(
10,
20
);
Here, double is explicitly specified as the template type.
template <typename T, typename U, typename V>
void show(
T a,
U b,
V c
) {
std::cout <<
a << " "
<< b << " "
<< c;
}
A template can have multiple type parameters when a generic operation requires them.
Templates can also be used with classes.
template <typename T>
class Box {
private:
T value;
public:
Box(T v) {
value = v;
}
T getValue() {
return value;
}
};
The class can store different types depending on the template argument.
Box<int> intBox(100);
Box<double> doubleBox(25.5);
std::cout <<
intBox.getValue()
<< std::endl;
std::cout <<
doubleBox.getValue();
The template argument specifies the type used by the class.
#include <iostream>
template <typename T>
class Calculator {
public:
T add(
T a,
T b
) {
return a + b;
}
T multiply(
T a,
T b
) {
return a * b;
}
};
int main() {
Calculator<int> calc;
std::cout <<
calc.add(10, 20)
<< std::endl;
std::cout <<
calc.multiply(5, 4);
return 0;
}
template <typename T, typename U>
class Pair {
private:
T first;
U second;
public:
Pair(T a, U b)
: first(a),
second(b) {
}
void display() {
std::cout <<
first << " "
<< second;
}
};
Different types can be stored in the same class template.
A class template can provide a default type for a template parameter.
template <
typename T = int
>
class Number {
private:
T value;
public:
Number(T v)
: value(v) {
}
T getValue() {
return value;
}
};
If no type is specified, int is used.
Template specialization allows a programmer to provide a specialized implementation for a particular type.
template <typename T>
class Printer {
public:
void print(T value) {
std::cout <<
value;
}
};
template <>
class Printer<bool> {
public:
void print(bool value) {
std::cout <<
(value ? "true" : "false");
}
};
The second class provides a special implementation for
bool.
template <typename T>
void display(T value) {
std::cout <<
value;
}
template <>
void display<bool>(bool value) {
std::cout <<
(value ? "TRUE" : "FALSE");
}
A function template can also have a specialized implementation for a specific type.
Templates can also have non-type parameters such as integer values.
template <
typename T,
int SIZE
>
class Array {
private:
T data[SIZE];
public:
int size() {
return SIZE;
}
};
Here, SIZE is a compile-time value rather than a type.
template <typename T, int SIZE>
class Array {
private:
T data[SIZE];
public:
void set(
int index,
T value
) {
if(index >= 0 &&
index < SIZE) {
data[index] = value;
}
}
T get(int index) {
return data[index];
}
int size() {
return SIZE;
}
};
int main() {
Array<int, 5> numbers;
numbers.set(0, 100);
std::cout <<
numbers.get(0);
return 0;
}
Templates allow one generic implementation to work with many compatible types.
template <typename T>
T maximum(
T a,
T b
) {
return a > b ? a : b;
}
int a = maximum(10, 20);
double b =
maximum(10.5, 5.5);
This reduces the need to write duplicate functions.
Templates provide compile-time type checking.
template <typename T>
T multiply(T a, T b) {
return a * b;
}
int result =
multiply(5, 10);
The compiler checks whether the requested operation is valid for the selected type.
The C++ Standard Library uses templates extensively.
Examples include:
std::vector<T>std::list<T>std::map<K, V>std::set<T>std::pair<T, U>#include <vector>
std::vector<int> numbers;
std::vector<double> prices;
The same container template can work with different element types.
Many standard algorithms are implemented as templates so that they can work with different container and element types.
#include <algorithm>
#include <vector>
std::vector<int> numbers = {
40, 10, 30, 20
};
std::sort(
numbers.begin(),
numbers.end()
);
The generic algorithm can operate on many compatible types.
template declaration.#include <iostream>
template <typename T>
class Calculator {
public:
T add(
T a,
T b
) {
return a + b;
}
T subtract(
T a,
T b
) {
return a - b;
}
T multiply(
T a,
T b
) {
return a * b;
}
};
int main() {
Calculator<int> intCalc;
Calculator<double> doubleCalc;
std::cout <<
intCalc.add(10, 20)
<< std::endl;
std::cout <<
doubleCalc.multiply(
2.5,
4.0
);
return 0;
}
The same calculator class can work with different numeric types.
| Concept | Meaning |
|---|---|
| Template | A blueprint for writing generic functions or classes. |
| Function Template | A generic function that can work with different types. |
| Class Template | A generic class that can work with different types. |
| typename | Common keyword used to declare a type template parameter. |
| Template Parameter | A placeholder for a type or compile-time value. |
| Specialization | A customized implementation for a particular template argument. |
| Non-Type Parameter | A compile-time value used as a template parameter. |
template <typename T>
T maximum(
T a,
T b
) {
return a > b ? a : b;
}
int main() {
std::cout <<
maximum(10, 20)
<< std::endl;
std::cout <<
maximum(5.5, 2.5);
return 0;
}
Templates allow C++ programmers to create reusable, type-safe, generic code that can work with many compatible data types.
typename is commonly used for type parameters.Question: What is the main purpose of templates in C++?