LearnContact
Lesson 2610 min read

Templates

Writing separate functions for every data type leads to duplicate code. In this lesson, you will learn how C++ uses templates to write generic functions and classes that work with multiple data types.

Introduction

In the previous lesson, you learned about abstraction. Now consider a common programming problem: you want to create a function that adds two values.

If the values are integers, you can create an integer function. If the values are decimal numbers, you may create another function for double values. The logic remains exactly the same, but the data type changes.

Repeated Functions
int add(int a, int b)
{
    return a + b;
}

double add(double a, double b)
{
    return a + b;
}

float add(float a, float b)
{
    return a + b;
}

Writing separate versions of the same logic creates duplicate code. If the logic changes, every version may need to be updated separately.

Separate Functions

  • One function for int.
  • Another function for double.
  • Another function for float.
  • Repeated logic for every type.

One Template

  • Write the logic once.
  • Use it with int.
  • Use it with double.
  • Use it with many compatible types.
Write Generic Template
Use a Data Type
Compiler Creates Required Version
Execute Generated Code
The Main Idea

Templates allow you to write generic code once and use it with multiple compatible data types.

What is a Template?

A template is a C++ feature that allows you to define a generic function or class whose behavior can work with different data types.

Instead of writing separate versions of similar code, you define the logic once using one or more template parameters. The compiler then creates the required specialization when the template is used.

Template Concept
Generic Template
       │
       ├── Used with int
       │       ▼
       │   int Version
       │
       ├── Used with double
       │       ▼
       │   double Version
       │
       └── Used with Another Compatible Type
               ▼
           Required Version
ConceptMeaning
TemplateA generic definition
Template ParameterA placeholder used by the template
Template ArgumentThe actual type or value supplied
InstantiationCreation of a specific template version
Generic ProgrammingWriting algorithms and structures that work with different types
Generic Function
template <typename T>
T add(T a, T b)
{
    return a + b;
}
How T Changes
add(10, 20)
      │
      ▼
T becomes int

add(2.5, 3.5)
      │
      ▼
T becomes double
Simple Definition

A template is a generic blueprint that the compiler can use to create code for specific types.

Why Do We Need Templates?

Many programming operations use the same logic for different types. Without templates, developers may repeat nearly identical functions and classes.

Without Templates

  • Similar code is written repeatedly.
  • Code duplication increases.
  • Maintenance becomes more difficult.
  • Changes may need to be repeated.
  • Programs can become unnecessarily larger.

With Templates

  • Generic code is written once.
  • Duplicate logic is reduced.
  • Maintenance becomes easier.
  • Multiple compatible types are supported.
  • Reusable libraries become possible.
Without Templates
Integer Logic
     +
Double Logic
     +
Float Logic
     +
Other Type Logic
     =
Repeated Code
With Templates
        One Generic Template
                 │
        ┌────────┼────────┐
        ▼        ▼        ▼
       int     double    float

Reusability

The same generic definition can support multiple compatible types.

Less Duplication

Repeated implementations can often be replaced with one template.

Type Safety

Template operations are checked by the compiler for the instantiated types.

Maintainability

Shared logic can be updated in one generic definition.

Generic Libraries

Reusable containers and algorithms can work with many types.

Compile-Time Generation

Required template versions are instantiated during compilation.

Real-World Analogy

Imagine a bottle manufacturing company that needs to produce bottles in several sizes.

Instead of building a completely separate machine for every bottle size, the company uses one adjustable machine. The machine follows the same general process but adapts according to the required size.

Adjustable Machine
       Generic Bottle Machine
                 │
       ┌─────────┼─────────┐
       ▼         ▼         ▼
    250 ml     500 ml    1 Litre
     Bottle     Bottle     Bottle
Bottle FactoryC++ Templates
Adjustable machineGeneric template
Bottle size settingTemplate argument
250 ml bottleSpecific type version
500 ml bottleAnother type version
Same production processSame generic logic
Create Generic Machine
Provide Required Setting
Adjust Machine
Produce Required Bottle
One Blueprint, Different Results

A template defines the reusable pattern. The supplied template argument determines the specific version that is used.

Types of Templates

At this stage, the two main categories of templates you need to understand are function templates and class templates.

1️⃣ Function Templates

Create generic functions that can perform the same operation with different compatible types.

2️⃣ Class Templates

Create generic classes whose members can use different types.

Template Categories
Templates
   │
   ├── Function Templates
   │       │
   │       └── Generic Operations
   │
   └── Class Templates
           │
           └── Generic Types and Data Structures
Template TypeCreatesExample Use
Function TemplateGeneric functionadd(), maximum(), swap()
Class TemplateGeneric classBox<T>, Stack<T>, Container<T>
Same Principle

Both function templates and class templates use template parameters to replace specific types with generic placeholders.

Function Templates

A function template defines a generic function that can operate with different compatible types.

The template declaration appears immediately before the function definition.

General Syntax
template <typename T>
return_type functionName(T value)
{
    // Generic code
}
PartMeaning
templateBegins a template declaration
typenameIntroduces a type template parameter
TThe name of the type placeholder
T valueA parameter whose type depends on T
Generic codeLogic written using the template parameter
Reading the Declaration
template <typename T>
   │          │    │
   │          │    └── Type Parameter Name
   │          └─────── Declares a Type Parameter
   └────────────────── Template Declaration

The name T is conventional, but it is not a special keyword. You can use another meaningful name.

Different Parameter Names
template <typename T>
void show(T value)
{
}

template <typename Type>
void display(Type value)
{
}

template <typename ElementType>
void print(ElementType value)
{
}
typename and class

For declaring a type template parameter, typename and class are generally interchangeable in declarations such as template <typename T> and template <class T>.

Example 1: Function Template

The following function template adds two values of the same deduced type.

Example 1: Function Template
#include <iostream>

template <typename T>
T add(T a, T b)
{
    return a + b;
}

int main()
{
    std::cout << add(10, 20)
              << std::endl;

    std::cout << add(2.5, 3.5)
              << std::endl;

    return 0;
}

How the Program Works

  • The compiler reads the add() function template.
  • The first call passes two int values.
  • T is deduced as int for that call.
  • The second call passes two double values.
  • T is deduced as double for that call.
  • The required function specializations are instantiated.
First Call
add(10, 20)
     │
     ▼
T = int
     │
     ▼
add<int>(10, 20)
     │
     ▼
Result: 30
Second Call
add(2.5, 3.5)
       │
       ▼
T = double
       │
       ▼
add<double>(2.5, 3.5)
       │
       ▼
Result: 6
Conceptual Instantiations
int add(int a, int b)
{
    return a + b;
}

double add(double a, double b)
{
    return a + b;
}
Output
30
6
Conceptual View

The generated specializations are a useful way to understand template instantiation. The exact internal implementation is handled by the compiler.

Class Templates

A class template defines a family of classes using one or more template parameters.

Class templates are especially useful for containers and data structures that should store different types while using the same class logic.

General Syntax
template <typename T>
class ClassName
{
    T memberVariable;
};
Simple Box Template
template <typename T>
class Box
{
public:
    T value;
};
Class Template Concept
          Box<T>
             │
      ┌──────┼──────┐
      ▼      ▼      ▼
 Box<int> Box<double> Box<char>
Class UseT BecomesMember Type
Box<int>intint
Box<double>doubledouble
Box<char>charchar
Explicit Type Argument

When creating an object from a class template, the type argument is commonly written inside angle brackets, such as Box<int>.

Example 2: Class Template

The following Box class template can store and display values of different types.

Example 2: Class Template
#include <iostream>

template <typename T>
class Box
{
public:
    T value;

    void display()
    {
        std::cout << value
                  << std::endl;
    }
};

int main()
{
    Box<int> box1;
    box1.value = 100;
    box1.display();

    Box<double> box2;
    box2.value = 55.5;
    box2.display();

    return 0;
}

How the Program Works

  • Box is declared as a class template.
  • T represents the type of the value member.
  • Box<int> creates an int-based Box specialization.
  • box1 stores the integer value 100.
  • Box<double> creates a double-based Box specialization.
  • box2 stores the double value 55.5.
  • Each object uses the same class template logic.
Template Instantiation
Box<T>
  │
  ├── Box<int>
  │      │
  │      └── value is int
  │
  └── Box<double>
         │
         └── value is double
Output
100
55.5
One Class Definition

The Box template provides one generic class definition that can be instantiated with different types.

Example 3: Using Different Data Types

A function template can also be instantiated for very different types when the operations inside the function are valid for those types.

Example 3: Different Types
#include <iostream>

template <typename T>
void show(T value)
{
    std::cout << value
              << std::endl;
}

int main()
{
    show(100);
    show(25.75);
    show("Hello");

    return 0;
}
Function CallDeduced T
show(100)int
show(25.75)double
show("Hello")String-literal-related character array type
Template Uses
show(100)
   │
   └── Integer Value

show(25.75)
   │
   └── Double Value

show("Hello")
   │
   └── String Literal
Output
100
25.75
Hello
The Operations Must Be Valid

A template can only be instantiated successfully when the operations used inside the template are valid for the supplied type.

Operation Requirement
template <typename T>
T add(T a, T b)
{
    return a + b;
}

// The supplied type must support
// the + operation used by the template.

Memory Representation

Different class-template specializations are different types. Their object sizes and memory layouts depend on the members produced for the supplied template arguments.

Objects
Box<int> box1;
Box<double> box2;
Conceptual Memory Layout
Box<int> box1

+----------------------+
| value                |
| Type: int            |
| Example Value: 100   |
+----------------------+


Box<double> box2

+----------------------+
| value                |
| Type: double         |
| Example Value: 55.5  |
+----------------------+
ObjectSpecializationMember Type
box1Box<int>int
box2Box<double>double
Separate Types
Box<int>
   │
   └── One Class Specialization

Box<double>
   │
   └── Another Class Specialization
Do Not Memorize Fixed Byte Counts

The exact size of types such as int and double can depend on the implementation and platform. Use sizeof when the exact size matters.

Important

Box<int> and Box<double> are different class-template specializations and therefore different types.

Program Execution Flow

Templates are processed as part of compilation. When a template is used with particular arguments, the compiler determines and instantiates the required specialization.

Write Template Definition
Use Template
Determine Template Arguments
Instantiate Required Specialization
Compile Program
Execute Program
Template Processing Flow
Source Code
    │
    ▼
Template Definition
    │
    ▼
Template Use
    │
    ▼
Determine Template Arguments
    │
    ▼
Instantiate Required Specialization
    │
    ▼
Compile
    │
    ▼
Executable Program
    │
    ▼
Run
StageWhat Happens
1The programmer writes a generic template
2The template is used with particular arguments
3The compiler determines the required specialization
4The required specialization is instantiated
5The program is compiled
6The compiled program executes normally
Compile-Time Feature

Template instantiation is a compile-time mechanism. The resulting compiled functions and classes execute normally at runtime.

Function Template vs Class Template

Function templates and class templates use the same generic programming principle but generate different kinds of program elements.

FeatureFunction TemplateClass Template
PurposeDefines generic functionsDefines generic classes
ProducesFunction specializationsClass specializations
Used ForGeneric operations and algorithmsGeneric types and data structures
Exampleadd<T>()Box<T>
Type DeductionOften possible from function argumentsType arguments are commonly written explicitly
Typical UseCalculations and reusable operationsContainers and reusable object structures

Function Template

  • Represents generic behavior.
  • Used for reusable operations.
  • Can often deduce type arguments.
  • Example: add() or maximum().

Class Template

  • Represents a generic type.
  • Used for reusable object structures.
  • Creates different class specializations.
  • Example: Box<T> or Stack<T>.
Function Template
template <typename T>
T maximum(T a, T b)
{
    return a > b ? a : b;
}
Class Template
template <typename T>
class Box
{
public:
    T value;
};

Real-World Applications

Templates are a major part of modern C++ and are widely used in reusable libraries, generic algorithms, and data structures.

Standard Library Containers

Containers such as vector, list, queue, and stack are templates that can store different element types.

Mathematical Libraries

Generic calculations can support multiple numeric or user-defined types.

Data Structures

Linked lists, trees, graphs, and containers can be designed generically.

Game Development

Generic containers and utilities can work with enemies, items, components, and other game objects.

Generic Algorithms

Operations such as searching and sorting can be written to work with many compatible types.

Reusable Libraries

Library authors can provide flexible components without rewriting them for every type.

Standard Library Example
#include <vector>
#include <string>

std::vector<int> numbers;
std::vector<double> prices;
std::vector<std::string> names;
One Container Template
          vector<T>
              │
      ┌───────┼────────┐
      ▼       ▼        ▼
 vector<int>  │  vector<string>
              │
       vector<double>
Foundation of Generic C++ Libraries

Templates are a core mechanism behind many reusable components in the C++ standard library.

Advantages of Templates

Code Reusability

Write generic logic once and reuse it with multiple compatible types.

Reduced Duplication

Avoid maintaining several nearly identical implementations.

Type Safety

The compiler checks whether instantiated template operations are valid for the supplied types.

Maintainability

Shared logic can be changed in one template definition.

Library Design

Generic containers and algorithms can be provided to many users.

Compile-Time Specialization

Specific template versions are created as part of compilation.

  • Supports generic programming.
  • Reduces repeated code.
  • Improves reusability.
  • Supports different compatible types.
  • Provides compile-time type checking.
  • Enables reusable containers and algorithms.
  • Forms a major foundation of the C++ standard library.
  • Makes many libraries more flexible.
Templates Also Have Trade-Offs

Templates can produce complex compiler errors, increase compilation work, and make code harder to understand when used unnecessarily.

Common Beginner Mistakes

Forgetting the template Declaration

A template parameter such as T must be introduced by a template declaration.

Passing Conflicting Types

A single deduced template parameter cannot always satisfy arguments of different types.

Confusing Templates with Overloading

Overloading defines multiple functions, while templates define generic patterns that can be instantiated.

Assuming Template Generation Happens at Runtime

Template instantiation is part of compilation.

Using Unsupported Operations

The supplied type must support the operations used inside the template.

Overusing Templates

Templates should solve genuine generic programming problems, not make simple code unnecessarily complicated.

Missing Template Declaration
// ❌ Incorrect
typename T
void show(T value)
{
}

// ✅ Correct
template <typename T>
void show(T value)
{
}
Conflicting Type Deduction
template <typename T>
T add(T a, T b)
{
    return a + b;
}

// ❌ T cannot be deduced as both
// int and double in this call
add(10, 2.5);
Consistent Types
add(10, 20);
add(10.0, 2.5);
Multiple Template Parameters
template <typename T, typename U>
auto add(T a, U b)
{
    return a + b;
}

add(10, 2.5);

Function Overloading

  • Multiple function definitions.
  • Each overload has its own parameter list.
  • Useful when behavior differs.

Function Template

  • One generic definition.
  • Instantiated for required types.
  • Useful when the logic is generic.
Read Template Errors Carefully

When template compilation fails, check the deduced types and verify that every operation used by the template is valid for those types.

Best Practices

  • Use templates when the same meaningful logic should work with multiple types.
  • Avoid templates when separate types require completely different behavior.
  • Use T for simple, obvious single-type templates.
  • Use descriptive names such as ElementType or ValueType when several template parameters are involved.
  • Keep generic requirements understandable.
  • Use override-like compiler checks where available in other language features, but remember templates rely on valid operations for supplied types.
  • Prefer standard library templates instead of recreating existing containers and algorithms.
  • Keep template definitions accessible where they are instantiated, commonly in header files.
  • Avoid unnecessary template complexity.
  • Test templates with multiple representative types.
  • Use multiple template parameters when the design genuinely requires different types.
  • Document assumptions about operations required from template arguments.
Simple Generic Function
template <typename T>
T maximum(T a, T b)
{
    return a > b ? a : b;
}
Descriptive Parameter Name
template <typename ElementType>
class Container
{
    ElementType value;
};

Poor Template Use

  • Different behavior for every type.
  • Unclear requirements.
  • Unnecessary layers of generic code.
  • Difficult-to-understand parameter names.

Good Template Use

  • Shared generic logic.
  • Clear type requirements.
  • Meaningful reusable behavior.
  • Simple and understandable design.
Use Generic Code for Generic Problems

Templates are most useful when the algorithm or data structure is conceptually the same across multiple types.

Frequently Asked Questions

What is a template?

A template is a C++ mechanism for defining generic functions and classes that can be instantiated with different arguments.

What is generic programming?

Generic programming is the practice of writing algorithms and data structures in terms of general requirements rather than one specific data type.

What are the main template types covered in this lesson?

Function templates and class templates.

What is a function template?

A function template defines a generic function that can be instantiated for different compatible types.

What is a class template?

A class template defines a family of classes parameterized by one or more template arguments.

What does typename T mean?

It declares T as a type template parameter that acts as a placeholder inside the template.

Is T a keyword?

No. T is only a conventional parameter name and can be replaced with another valid identifier.

Can we use class instead of typename?

Yes. For a type template parameter, declarations such as template <typename T> and template <class T> are generally equivalent.

Are templates processed at runtime?

No. Template instantiation is part of compilation. The compiled specializations then execute normally at runtime.

What is template instantiation?

Instantiation is the process of producing a specific specialization from a template for particular template arguments.

Can a function template use multiple template parameters?

Yes. A template can declare multiple parameters, such as template <typename T, typename U>.

Why can add(10, 2.5) fail for a single T parameter?

The compiler may be unable to deduce one T that matches both int and double arguments.

Are Box<int> and Box<double> the same type?

No. They are different specializations of the Box class template.

Do templates guarantee every type will work?

No. The operations used inside the template must be valid for the supplied template arguments.

Why are templates important?

They reduce duplication, support reusable generic code, and form a major foundation of the C++ standard library.

Key Takeaways

  • Templates enable generic programming in C++.
  • A template defines a reusable generic pattern.
  • Template parameters act as placeholders.
  • Template arguments provide specific types or values.
  • Function templates define generic functions.
  • Class templates define generic classes.
  • The template keyword begins a template declaration.
  • typename can introduce a type template parameter.
  • T is a conventional name, not a keyword.
  • Function template arguments can often be deduced from function arguments.
  • Class templates commonly use explicit type arguments such as Box<int>.
  • Templates are instantiated for the required arguments.
  • Template instantiation occurs as part of compilation.
  • Different class-template specializations are different types.
  • The memory layout of a class specialization depends on its generated members and supplied types.
  • The exact size of fundamental types can depend on the platform.
  • Template operations must be valid for the supplied types.
  • A single template parameter may fail when arguments require conflicting deductions.
  • Templates can use multiple template parameters.
  • Templates reduce duplicate code.
  • Templates improve reusability.
  • Templates support compile-time type checking.
  • Templates are heavily used by the C++ standard library.
  • Standard containers such as vector are class templates.
  • Templates should be used when the underlying logic is genuinely generic.

Summary

Templates are one of the most important generic programming features in C++. They allow functions and classes to be written in terms of parameters instead of being limited to one specific type.

Function templates define generic operations. When a function template is called, the compiler can often deduce the required type arguments from the function arguments.

Class templates define families of related class specializations. For example, Box<int> and Box<double> are created from the same class template but are different types.

Template instantiation is part of compilation. The compiler creates the required specializations, and the resulting compiled code executes normally at runtime.

Templates reduce duplicate code, improve reusability, and support type-safe generic libraries. They form a major foundation of the C++ standard library and are used extensively in containers, algorithms, data structures, and reusable application components.

Templates are most effective when the underlying logic is genuinely the same across multiple types. They should simplify reusable code rather than introduce unnecessary complexity.

In the next lesson, you will learn about namespaces and how C++ uses them to organize names and prevent naming conflicts in larger programs.

Next Lesson →

Namespaces