← Back to Curriculum

Templates and Generic Programming

šŸ“š Lesson 4 of 10 ā±ļø 45 min

Templates and Generic Programming

45 min

Templates are C++'s mechanism for generic programming, allowing you to write code that works with any type without sacrificing type safety. Templates enable code reuse at the source level—the compiler generates specialized versions of template code for each type used. This approach eliminates the need for function overloading for different types and enables type-safe generic containers and algorithms.

Function templates define generic functions that work with multiple types. The template syntax uses angle brackets (<>) to specify type parameters. When you call a template function, the compiler deduces the types from the arguments and generates the appropriate specialized function. Template type deduction is powerful but can sometimes require explicit type specification using angle brackets.

Class templates create generic classes that can work with any type. The Standard Template Library (STL) is built entirely on class templates—containers like vector, list, and map are all class templates. Class templates enable you to create type-safe, reusable data structures that work with any compatible type, eliminating the need to write separate implementations for each type.

Template specialization allows you to provide custom implementations for specific types. Full specialization creates a completely custom version for a specific type, while partial specialization (for class templates) allows customizations for type patterns. Specialization is useful for optimizing performance for specific types or handling edge cases differently.

Template metaprogramming is an advanced technique that uses templates to perform computations at compile time. While complex, template metaprogramming enables powerful optimizations and type manipulations. Modern C++ features like constexpr functions provide more readable alternatives for many compile-time computations, but templates remain essential for type-level programming.

Concepts (C++20) add constraints to templates, making template requirements explicit and improving error messages. Concepts specify what operations a type must support to be used with a template, making templates more self-documenting and easier to use correctly. While concepts are a newer feature, understanding basic template constraints helps write better template code even in C++11/14/17.

Key Concepts

  • Templates enable generic programming with type parameters.
  • Function templates work with any compatible type.
  • Class templates create type-safe generic containers.
  • Template specialization provides custom behavior for specific types.
  • Templates are instantiated at compile time for each used type.

Learning Objectives

Master

  • Creating function templates for generic operations
  • Implementing class templates for reusable containers
  • Using template specialization for type-specific behavior
  • Understanding template type deduction and explicit specification

Develop

  • Generic programming thinking
  • Understanding compile-time code generation
  • Designing reusable, type-safe components

Tips

  • Use typename or class for type parameters: template<typename T> or template<class T>.
  • Specify types explicitly when needed: myFunc<int>(5, 10);
  • Use template specialization for type-specific optimizations.
  • Keep template code in header files (templates are compiled on use).

Common Pitfalls

  • Not understanding template instantiation, causing linker errors.
  • Putting template implementations in .cpp files, breaking compilation.
  • Creating overly complex templates, reducing readability.
  • Not considering template bloat (code size increase from instantiations).

Summary

  • Templates enable type-safe generic programming.
  • Function and class templates work with any compatible type.
  • Template specialization allows type-specific customizations.
  • Templates are instantiated at compile time for each used type.

Exercise

Create function and class templates for generic operations.

#include <iostream>
#include <string>

// Function template
template<typename T>
T maximum(T a, T b) {
    return (a > b) ? a : b;
}

// Class template
template<typename T>
class Container {
private:
    T data;
    
public:
    Container(const T& value) : data(value) {}
    
    T getValue() const {
        return data;
    }
    
    void setValue(const T& value) {
        data = value;
    }
};

int main() {
    // Function template usage
    std::cout << "Max of 5 and 3: " << maximum(5, 3) << std::endl;
    std::cout << "Max of 3.14 and 2.71: " << maximum(3.14, 2.71) << std::endl;
    std::cout << "Max of 'a' and 'b': " << maximum('a', 'b') << std::endl;
    
    // Class template usage
    Container<int> intContainer(42);
    Container<double> doubleContainer(3.14);
    Container<std::string> stringContainer("Hello");
    
    std::cout << "Int container: " << intContainer.getValue() << std::endl;
    std::cout << "Double container: " << doubleContainer.getValue() << std::endl;
    std::cout << "String container: " << stringContainer.getValue() << std::endl;
    
    return 0;
}

Exercise Tips

  • Try different types: maximum(5, 3), maximum(3.14, 2.71), maximum('a', 'b').
  • Create template with multiple types: template<typename T, typename U>.
  • Use template specialization: template<> class Container<bool> { ... };
  • Experiment with template parameters: template<int N> for non-type parameters.

Code Editor

Output