C++ Templates: A Comprehensive Guide to Generic Programming

Entroduction to Generic Programming When implementing a swap function, we might write multiple overloaded versions:

void Exchange(int& a, int& b)
{
    int temp = a;
    a = b;
    b = temp;
}

void Exchange(char& a, char& b)
{
    char temp = a;
    a = b;
    b = temp;
}

void Exchange(double& a, double& b)
{
    double temp = a;
    a = b;
    b = temp;
}

While function overloading works, it has drawbacks:

  1. Low code reusability - each type requires a separate function implementation
  2. Poor maintainability - errors in one function can affect others

What if we could provide a blueprint to the compiler that generates code for different types?

Generic programming: Writing type-agnostic code that can be reused across different data types. Templates form the foundation of generic programming.

Function Templates

  1. Function Template Syntax Keyword: template
template<typename T>
void Exchange(T& a, T& b)
{
    T temp = a;
    a = b;
    b = temp;
}

Note: typename is a keyword that can be replaced with class (but not struct).

  1. Template Implementation Principle Templates are processed by the compiler, wich generates specific function implementations based on the template. During the compilation phase, the compiler analyzes the template usage and generates appropriate function instances for the actual types used.
  2. Template Instantiation

3.1 Implicit Instantiation The compiler deduces the actual type from the arguments passed:

template<class T>
T Sum(const T& a, const T& b)
{
    return a + b;
}

int main()
{
    int num1 = 15, num2 = 25;
    double dec1 = 15.5, dec2 = 25.5;
    
    Sum(num1, num2);
    Sum(dec1, dec2);
    return 0;
}

3.2 Explicit Instantiation Specify the template parameter type explicitly:

int main(void)
{
    int value1 = 15;
    double value2 = 25.0;
    
    // Explicit instantiation
    Sum<int>(value1, value2);
    return 0;
}

  1. Template Parameter Matching Rules

4.1 Non-template and Template Functions Coexistence A non-template function can coexist with a template function of the same name:

// Specialized addition for integers
int Sum(int a, int b)
{
    return a + b;
}

// Generic addition template
template<class T>
T Sum(T a, T b)
{
    return a + b;
}

void Test()
{
    Sum(1, 2); // Calls non-template version
    Sum<int>(1, 2); // Calls compiler-generated template version
}

4.2 Priority in Function Selection When both non-template and template functions are available, the non-template version is preferred unless the template provides a better match:

// Specialized addition for integers
int Sum(int a, int b)
{
    return a + b;
}

// Generic addition with different parameter types
template<class T1, class T2>
T1 Sum(T1 a, T2 b)
{
    return a + b;
}

void Test()
{
    Sum(1, 2); // Calls non-template version
    Sum(1, 2.0); // Template provides better match
}

4.3 Type Conversion Rules Template functions don't allow automatic type conversion, while regular functions do.

Class Templates

  1. Class Template Definition
template<class T1, class T2, ..., class Tn>
class ClassName
{
    // Member definitions
};

// Dynamic array implementation
template<class T>
class DynamicArray
{
public:
    DynamicArray(size_t capacity = 10)
        : _data(new T[capacity])
        , _currentSize(0)
        , _maxCapacity(capacity)
    {}
    
    // Destructor declaration (defined outside the class)
    ~DynamicArray();
    
    void Append(const T& value);
    void RemoveLast();
    
    size_t GetSize() { return _currentSize; }
    
    T& operator[](size_t index)
    {
        assert(index < _currentSize);
        return _data[index];
    }
    
private:
    T* _data;
    size_t _currentSize;
    size_t _maxCapacity;
};

// Note: When defining class template methods outside the class, include the template parameter list
template <class T>
DynamicArray<T>::~DynamicArray()
{
    if(_data)
        delete[] _data;
    _currentSize = _maxCapacity = 0;
}

Important: When separating class template declarations and definitions, keep them in the same file. Separating into different files will cause compilation errors.

  1. Template Instantiation Note: DynamicArray is not a concrete class; DynamicArray<int> is the actual type.
DynamicArray<int> intArray;
DynamicArray<double> doubleArray;

Tags: C++ Templates Generic Programming Function Templates Class Templates

Posted on Tue, 02 Jun 2026 18:22:20 +0000 by danoush