C++ Function Templates
Generic functions that work with any data type
๐ฏ What are Function Templates?
Function templates create generic functions that work with multiple data types. Instead of writing separate functions for each type, templates generate them automatically.
// Template function works with any type
#include <iostream>
using namespace std;
template <typename T>
T getMax(T a, T b) {
return (a > b) ? a : b;
}
int main() {
cout << getMax(5, 3) << endl; // Works with int
cout << getMax(2.7, 1.9) << endl; // Works with double
cout << getMax('z', 'a') << endl; // Works with char
return 0;
}
Output:
5
2.7
z
Template Concepts
Template Keyword
Declares a template function
template <typename T>
T myFunction(T param);
Type Parameter
Placeholder for any data type
template <typename T>
// T can be int, double, etc.
Automatic Deduction
Compiler determines the type
myFunction(5); // T = int
myFunction(3.14); // T = double
Multiple Types
Templates with multiple parameters
template <typename T, typename U>
void func(T a, U b);
๐น Basic Template Syntax
Function templates in C++ provide a blueprint for generating type-agnostic functions using the
template <typename T> syntax. They allow a single function definition to work with
multiple data types, promoting code reuse and reducing duplication. For example, a template
add(T a, T b) can handle integers, doubles, and floats. Templates are resolved at compile-time,
ensuring type safety and performance, and are foundational for generic programming in C++ libraries like STL.
#include <iostream>
using namespace std;
// Template declaration
template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
// Compiler automatically deduces types
cout << "Int addition: " << add(5, 3) << endl;
cout << "Double addition: " << add(2.5, 3.7) << endl;
cout << "Float addition: " << add(1.2f, 2.8f) << endl;
// You can also explicitly specify the type
cout << "Explicit int: " << add<int>(10, 20) << endl;
return 0;
}
Output:
Int addition: 8
Double addition: 6.2
Float addition: 4
Explicit int: 30
๐น Multiple Template Parameters
Templates can define multiple type parameters to handle functions requiring several generic types.
For example, template <typename T1, typename T2> allows pairs of different types, useful in
containers, utility functions, or operations like max() comparing mixed types. This extends
flexibility, supports heterogeneous data processing, and enables advanced generic patterns. Multiple template
parameters are common in data structures (e.g., maps), algorithms, and adapter classes where type independence is
crucial.
#include <iostream>
using namespace std;
// Template with two different types
template <typename T, typename U>
void printPair(T first, U second) {
cout << "First: " << first << ", Second: " << second << endl;
}
// Template that returns the larger type
template <typename T, typename U>
auto getMax(T a, U b) -> decltype(a > b ? a : b) {
return (a > b) ? a : b;
}
int main() {
printPair(42, "Hello");
printPair(3.14, 'A');
printPair("World", 100);
cout << "Max of 5 and 3.7: " << getMax(5, 3.7) << endl;
cout << "Max of 2.1 and 8: " << getMax(2.1, 8) << endl;
return 0;
}
Output:
First: 42, Second: Hello
First: 3.14, Second: A
First: World, Second: 100
Max of 5 and 3.7: 5
Max of 2.1 and 8: 8
๐น Practical Template Examples
Real-world template examples include generic swap, min/max, and array printing functions that work across
types. A template swap(T& a, T& b) exchanges values of any type, while
printArray(T arr[], int size) displays arrays of integers, doubles, etc. These examples demonstrate
templatesโ power in creating reusable, type-safe utilities. Practical use in algorithms, containers, and helpers
reduces code bloat, enhances maintainability, and showcases C++โs ability to write once, use everywhere.
#include <iostream>
using namespace std;
// Template for swapping values
template <typename T>
void swapValues(T &a, T &b) {
T temp = a;
a = b;
b = temp;
}
// Template for finding minimum of three values
template <typename T>
T getMin(T a, T b, T c) {
T min = a;
if (b < min) min = b;
if (c < min) min = c;
return min;
}
// Template for array printing
template <typename T>
void printArray(T arr[], int size) {
cout << "Array: ";
for (int i = 0; i < size; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
int main() {
// Swapping different types
int x = 10, y = 20;
cout << "Before swap: x = " << x << ", y = " << y << endl;
swapValues(x, y);
cout << "After swap: x = " << x << ", y = " << y << endl;
double a = 5.5, b = 2.2;
swapValues(a, b);
cout << "Swapped doubles: a = " << a << ", b = " << b << endl;
// Finding minimum
cout << "Min of 5, 2, 8: " << getMin(5, 2, 8) << endl;
cout << "Min of 3.7, 1.2, 9.1: " << getMin(3.7, 1.2, 9.1) << endl;
// Printing arrays
int intArr[] = {1, 2, 3, 4, 5};
double doubleArr[] = {1.1, 2.2, 3.3};
printArray(intArr, 5);
printArray(doubleArr, 3);
return 0;
}
Output:
Before swap: x = 10, y = 20
After swap: x = 20, y = 10
Swapped doubles: a = 2.2, b = 5.5
Min of 5, 2, 8: 2
Min of 3.7, 1.2, 9.1: 1.2
Array: 1 2 3 4 5
Array: 1.1 2.2 3.3
๐น Template Specialization
Template specialization allows custom implementations for specific types, overriding the generic
template. For instance, a generic process() template might handle numbers, but a string
specialization could compute length instead. This enables optimized or type-specific behavior while retaining a
uniform interface. Specialization is useful for edge cases, performance tuning, or when certain types require unique
logic, commonly seen in libraries, serialization, and type traits within C++ standard templates.
#include <iostream>
using namespace std;
// General template
template <typename T>
void process(T value) {
cout << "Processing general type: " << value << endl;
}
// Specialized template for strings
template <>
void process<string>(string value) {
cout << "Processing string (length " << value.length() << "): " << value << endl;
}
// Specialized template for char
template <>
void process<char>(char value) {
cout << "Processing character: '" << value << "' (ASCII: " << (int)value << ")" << endl;
}
int main() {
process(42); // Uses general template
process(3.14); // Uses general template
process("Hello"); // Uses string specialization
process('A'); // Uses char specialization
return 0;
}
Output:
Processing general type: 42
Processing general type: 3.14
Processing string (length 5): Hello
Processing character: 'A' (ASCII: 65)