C++ Templates
Overview
Templates are a powerful feature in C++ that allows writing generic code that works with multiple data types.
Function Templates
Basic Function Template
cpp
#include <iostream>
// Function template
template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
std::cout << "Int addition: " << add(5, 3) << std::endl;
std::cout << "Double addition: " << add(2.5, 3.7) << std::endl;
std::cout << "String addition: " << add(std::string("Hello"), std::string("World")) << std::endl;
return 0;
}Multiple Template Parameters
cpp
#include <iostream>
template <typename T, typename U>
void printTypes(T a, U b) {
std::cout << "First type: " << typeid(a).name() << ", value: " << a << std::endl;
std::cout << "Second type: " << typeid(b).name() << ", value: " << b << std::endl;
}
int main() {
printTypes(42, 3.14);
printTypes("Hello", 100);
return 0;
}Template Specialization
cpp
#include <iostream>
// General template
template <typename T>
T max_value(T a, T b) {
return (a > b) ? a : b;
}
// Template specialization for const char*
template <>
const char* max_value<const char*>(const char* a, const char* b) {
return (strcmp(a, b) > 0) ? a : b;
}
int main() {
std::cout << "Max of 5 and 3: " << max_value(5, 3) << std::endl;
std::cout << "Max of 2.5 and 3.7: " << max_value(2.5, 3.7) << std::endl;
std::cout << "Max of 'apple' and 'banana': " << max_value("apple", "banana") << std::endl;
return 0;
}Class Templates
Basic Class Template
cpp
#include <iostream>
template <typename T>
class Box {
private:
T value;
public:
Box(const T& val) : value(val) {}
void setValue(const T& val) {
value = val;
}
T getValue() const {
return value;
}
void display() const {
std::cout << "Box contains: " << value << std::endl;
}
};
int main() {
Box<int> intBox(42);
Box<double> doubleBox(3.14);
Box<std::string> stringBox("Hello, Templates!");
intBox.display();
doubleBox.display();
stringBox.display();
return 0;
}Class Template with Multiple Parameters
cpp
#include <iostream>
template <typename T, int SIZE>
class Array {
private:
T data[SIZE];
public:
T& operator[](int index) {
return data[index];
}
const T& operator[](int index) const {
return data[index];
}
int getSize() const {
return SIZE;
}
};
int main() {
Array<int, 5> intArray;
// Initialize array
for (int i = 0; i < 5; i++) {
intArray[i] = i * 10;
}
// Display array
for (int i = 0; i < intArray.getSize(); i++) {
std::cout << "intArray[" << i << "] = " << intArray[i] << std::endl;
}
return 0;
}Template Metaprogramming
Compile-time Computations
cpp
#include <iostream>
// Factorial using template metaprogramming
template <int N>
struct Factorial {
static const int value = N * Factorial<N - 1>::value;
};
// Base case
template <>
struct Factorial<0> {
static const int value = 1;
};
int main() {
std::cout << "Factorial of 5: " << Factorial<5>::value << std::endl;
std::cout << "Factorial of 10: " << Factorial<10>::value << std::endl;
return 0;
}Type Traits
cpp
#include <iostream>
#include <type_traits>
template <typename T>
void checkType(const T& value) {
if (std::is_integral<T>::value) {
std::cout << "Type is integral" << std::endl;
} else if (std::is_floating_point<T>::value) {
std::cout << "Type is floating point" << std::endl;
} else {
std::cout << "Type is other" << std::endl;
}
if (std::is_pointer<T>::value) {
std::cout << "Type is a pointer" << std::endl;
}
}
int main() {
int x = 42;
double y = 3.14;
int* ptr = &x;
checkType(x);
checkType(y);
checkType(ptr);
return 0;
}Variadic Templates (C++11)
cpp
#include <iostream>
// Variadic template function
template <typename... Args>
void print(Args... args) {
// Fold expression (C++17)
(std::cout << ... << args) << std::endl;
}
// Recursive variadic template (C++11)
template <typename T>
void printRecursive(T value) {
std::cout << value << std::endl;
}
template <typename T, typename... Args>
void printRecursive(T first, Args... args) {
std::cout << first << ", ";
printRecursive(args...);
}
int main() {
std::cout << "Using fold expression: ";
print(1, 2.5, "Hello", 'A');
std::cout << "Using recursion: ";
printRecursive(1, 2.5, "Hello", 'A');
return 0;
}