In C++, Templates provide a powerful mechanism for generic programming. They allow you to write code that works with any data type without rewriting the same logic for each type. This is the foundation of the C++ Standard Template Library (STL), which includes generic containers like std::vector and algorithms like std::sort.
By using templates, you can create a single function or class that can operate on different data types (like int, float, string, or even custom objects). The compiler generates the specific type-safe version of the function or class at compile time.
Templates in C++ come in two main flavors:
When you use a template with a specific type, the compiler performs template instantiation, generating the exact code needed for that type.
T, U, etc.).int, double).A function template allows you to define a function with generic types. Let's look at a simple example of a function that returns the maximum of two values.
#include <iostream>
// Define a function template
template <typename T>
T findMax(T a, T b) {
return (a > b) ? a : b;
}
int main() {
// Instantiating with int
std::cout << "Max of 5 and 10: " << findMax<int>(5, 10) << std::endl;
// Instantiating with double
std::cout << "Max of 3.14 and 2.71: " << findMax<double>(3.14, 2.71) << std::endl;
// Type inference allows us to omit the explicit type parameter <T>
std::cout << "Max of 'a' and 'z': " << findMax('a', 'z') << std::endl;
return 0;
}
Max of 5 and 10: 10 Max of 3.14 and 2.71: 3.14 Max of 'a' and 'z': z
In the code above, the compiler automatically generates three different versions of the findMax function: one for int, one for double, and one for char.
Class templates are incredibly useful when you want to build generic data structures. Here is an example of a simple generic Box class that can hold any type of value.
#include <iostream>
#include <string>
template <typename T>
class Box {
private:
T content;
public:
// Constructor
Box(T value) : content(value) {}
// Getter
T getContent() const {
return content;
}
// Setter
void setContent(T value) {
content = value;
}
};
int main() {
// A Box holding an integer
Box<int> intBox(100);
std::cout << "Integer Box contains: " << intBox.getContent() << std::endl;
// A Box holding a string
Box<std::string> stringBox("Hello Templates!");
std::cout << "String Box contains: " << stringBox.getContent() << std::endl;
return 0;
}
Integer Box contains: 100 String Box contains: Hello Templates!
Templates are not limited to a single parameter. You can specify multiple types. For example, a generic Pair class:
#include <iostream>
#include <string>
template <typename T1, typename T2>
class Pair {
public:
T1 first;
T2 second;
Pair(T1 f, T2 s) : first(f), second(s) {}
void print() {
std::cout << "First: " << first << ", Second: " << second << std::endl;
}
};
int main() {
Pair<int, std::string> p1(1, "One");
Pair<double, char> p2(3.14, 'A');
p1.print();
p2.print();
return 0;
}
First: 1, Second: One First: 3.14, Second: A
Sometimes, the generic implementation of a template doesn't work for a specific data type. In such cases, you can provide a specialized version of the template for that specific type.
#include <iostream>
#include <string>
// Generic Template
template <typename T>
void print(T value) {
std::cout << "Generic Print: " << value << std::endl;
}
// Template Specialization for std::string
template <>
void print<std::string>(std::string value) {
std::cout << "String Specialization Print: \"" << value << "\"" << std::endl;
}
int main() {
print(42); // Calls generic template
print(3.14); // Calls generic template
print(std::string("Hi")); // Calls specialized template
return 0;
}
Generic Print: 42 Generic Print: 3.14 String Specialization Print: "Hi"
Templates are the backbone of generic programming in C++. Now that you understand how to write your own Function and Class templates, you are ready to dive into the Standard Template Library (STL). The STL heavily utilizes templates to provide powerful containers like vectors, maps, and sets, alongside highly optimized algorithms.