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.
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.
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.
Generic Template
│
├── Used with int
│ ▼
│ int Version
│
├── Used with double
│ ▼
│ double Version
│
└── Used with Another Compatible Type
▼
Required Version| Concept | Meaning |
|---|---|
| Template | A generic definition |
| Template Parameter | A placeholder used by the template |
| Template Argument | The actual type or value supplied |
| Instantiation | Creation of a specific template version |
| Generic Programming | Writing algorithms and structures that work with different types |
template <typename T>
T add(T a, T b)
{
return a + b;
}add(10, 20)
│
▼
T becomes int
add(2.5, 3.5)
│
▼
T becomes doubleA 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.
Integer Logic
+
Double Logic
+
Float Logic
+
Other Type Logic
=
Repeated Code One Generic Template
│
┌────────┼────────┐
▼ ▼ ▼
int double floatReusability
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.
Generic Bottle Machine
│
┌─────────┼─────────┐
▼ ▼ ▼
250 ml 500 ml 1 Litre
Bottle Bottle Bottle| Bottle Factory | C++ Templates |
|---|---|
| Adjustable machine | Generic template |
| Bottle size setting | Template argument |
| 250 ml bottle | Specific type version |
| 500 ml bottle | Another type version |
| Same production process | Same generic logic |
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.
Templates
│
├── Function Templates
│ │
│ └── Generic Operations
│
└── Class Templates
│
└── Generic Types and Data Structures| Template Type | Creates | Example Use |
|---|---|---|
| Function Template | Generic function | add(), maximum(), swap() |
| Class Template | Generic class | Box<T>, Stack<T>, Container<T> |
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.
template <typename T>
return_type functionName(T value)
{
// Generic code
}| Part | Meaning |
|---|---|
| template | Begins a template declaration |
| typename | Introduces a type template parameter |
| T | The name of the type placeholder |
| T value | A parameter whose type depends on T |
| Generic code | Logic written using the template parameter |
template <typename T>
│ │ │
│ │ └── Type Parameter Name
│ └─────── Declares a Type Parameter
└────────────────── Template DeclarationThe name T is conventional, but it is not a special keyword. You can use another meaningful name.
template <typename T>
void show(T value)
{
}
template <typename Type>
void display(Type value)
{
}
template <typename ElementType>
void print(ElementType value)
{
}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.
#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.
add(10, 20)
│
▼
T = int
│
▼
add<int>(10, 20)
│
▼
Result: 30add(2.5, 3.5)
│
▼
T = double
│
▼
add<double>(2.5, 3.5)
│
▼
Result: 6int add(int a, int b)
{
return a + b;
}
double add(double a, double b)
{
return a + b;
}30
6The 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.
template <typename T>
class ClassName
{
T memberVariable;
};template <typename T>
class Box
{
public:
T value;
}; Box<T>
│
┌──────┼──────┐
▼ ▼ ▼
Box<int> Box<double> Box<char>| Class Use | T Becomes | Member Type |
|---|---|---|
| Box<int> | int | int |
| Box<double> | double | double |
| Box<char> | char | char |
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.
#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.
Box<T>
│
├── Box<int>
│ │
│ └── value is int
│
└── Box<double>
│
└── value is double100
55.5The 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.
#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 Call | Deduced T |
|---|---|
| show(100) | int |
| show(25.75) | double |
| show("Hello") | String-literal-related character array type |
show(100)
│
└── Integer Value
show(25.75)
│
└── Double Value
show("Hello")
│
└── String Literal100
25.75
HelloA template can only be instantiated successfully when the operations used inside the template are valid for the supplied type.
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.
Box<int> box1;
Box<double> box2;Box<int> box1
+----------------------+
| value |
| Type: int |
| Example Value: 100 |
+----------------------+
Box<double> box2
+----------------------+
| value |
| Type: double |
| Example Value: 55.5 |
+----------------------+| Object | Specialization | Member Type |
|---|---|---|
| box1 | Box<int> | int |
| box2 | Box<double> | double |
Box<int>
│
└── One Class Specialization
Box<double>
│
└── Another Class SpecializationThe exact size of types such as int and double can depend on the implementation and platform. Use sizeof when the exact size matters.
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.
Source Code
│
▼
Template Definition
│
▼
Template Use
│
▼
Determine Template Arguments
│
▼
Instantiate Required Specialization
│
▼
Compile
│
▼
Executable Program
│
▼
Run| Stage | What Happens |
|---|---|
| 1 | The programmer writes a generic template |
| 2 | The template is used with particular arguments |
| 3 | The compiler determines the required specialization |
| 4 | The required specialization is instantiated |
| 5 | The program is compiled |
| 6 | The compiled program executes normally |
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.
| Feature | Function Template | Class Template |
|---|---|---|
| Purpose | Defines generic functions | Defines generic classes |
| Produces | Function specializations | Class specializations |
| Used For | Generic operations and algorithms | Generic types and data structures |
| Example | add<T>() | Box<T> |
| Type Deduction | Often possible from function arguments | Type arguments are commonly written explicitly |
| Typical Use | Calculations and reusable operations | Containers 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>.
template <typename T>
T maximum(T a, T b)
{
return a > b ? a : b;
}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.
#include <vector>
#include <string>
std::vector<int> numbers;
std::vector<double> prices;
std::vector<std::string> names; vector<T>
│
┌───────┼────────┐
▼ ▼ ▼
vector<int> │ vector<string>
│
vector<double>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 can produce complex compiler errors, increase compilation work, and make code harder to understand when used unnecessarily.
Common Beginner Mistakes
A template parameter such as T must be introduced by a template declaration.
A single deduced template parameter cannot always satisfy arguments of different types.
Overloading defines multiple functions, while templates define generic patterns that can be instantiated.
Template instantiation is part of compilation.
The supplied type must support the operations used inside the template.
Templates should solve genuine generic programming problems, not make simple code unnecessarily complicated.
// ❌ Incorrect
typename T
void show(T value)
{
}
// ✅ Correct
template <typename T>
void show(T value)
{
}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);add(10, 20);
add(10.0, 2.5);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.
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.
template <typename T>
T maximum(T a, T b)
{
return a > b ? a : b;
}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.
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.