Skip to content

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;
}

Content is for learning and research only.