Menu
Coddy logo textTech

Function Templates

Part of the Object Oriented Programming section of Coddy's C++ journey — lesson 64 of 104.

Imagine writing a function to find the maximum of two integers, then realizing you need the same logic for doubles, and again for strings. Without templates, you'd write nearly identical functions for each type. Function templates solve this by letting you write the logic once and have the compiler generate type-specific versions automatically.

A function template uses the template keyword followed by template parameters in angle brackets:

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

int main() {
    std::cout << maximum(5, 3) << std::endl;       // Uses int version
    std::cout << maximum(3.14, 2.71) << std::endl; // Uses double version
    std::cout << maximum('a', 'z') << std::endl;   // Uses char version
}

The compiler examines each call and generates a concrete function for that specific type. This process is called template instantiation. You can also explicitly specify the type when needed:

std::cout << maximum<double>(5, 3.14) << std::endl;  // Forces double version

Templates can have multiple type parameters, enabling even more flexible designs:

template <typename T, typename U>
void printPair(T first, U second) {
    std::cout << first << ", " << second << std::endl;
}

printPair(42, "hello");    // T=int, U=const char*
printPair(3.14, 100);      // T=double, U=int

Function templates provide compile-time polymorphism - the type is determined when the code is compiled, not at runtime. This means zero runtime overhead compared to virtual functions, making templates ideal for performance-critical generic code.

challenge icon

Challenge

Easy

Let's build a utility toolkit using function templates to create reusable operations that work with any compatible type. You'll organize your generic functions in a header file and demonstrate their flexibility in your main program.

You'll create two files:

  • MathUtils.h: Define a collection of function templates that perform common operations:

    minimum — a template function that takes two values of the same type and returns the smaller one.

    clamp — a template function that takes three parameters: a value, a low bound, and a high bound. It returns the value constrained within the bounds (returns low if value is less than low, high if value is greater than high, otherwise returns the value itself).

    swapValues — a template function that takes two references of the same type and exchanges their values.

  • main.cpp: Read six inputs (each on a separate line):

    1. First integer
    2. Second integer
    3. A double value to clamp
    4. Low bound (double)
    5. High bound (double)
    6. A character

    Demonstrate your templates by:

    1. Finding the minimum of the two integers and printing: Min of <a> and <b>: <result>
    2. Finding the minimum of the characters 'm' and your input character, printing: Min of m and <char>: <result>
    3. Clamping the double value and printing: Clamp <value> to [<low>, <high>]: <result>
    4. Clamping the first integer to the range [0, 100] and printing: Clamp <value> to [0, 100]: <result>
    5. Swapping the two integers and printing: After swapValues: <a>, <b>

For example, with inputs 25, 10, 3.7, 1.0, 5.0, and z:

Min of 25 and 10: 10
Min of m and z: m
Clamp 3.7 to [1, 5]: 3.7
Clamp 25 to [0, 100]: 25
After swapValues: 10, 25

Notice how each template function works seamlessly with integers, doubles, and characters — the compiler generates the appropriate version for each type you use. Your swapValues function should modify the original variables through references, demonstrating that templates work with reference parameters just like regular functions.

Cheat sheet

Function templates allow you to write generic functions that work with multiple types. Use the template keyword followed by template parameters:

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

The compiler automatically generates type-specific versions through template instantiation:

maximum(5, 3);        // Generates int version
maximum(3.14, 2.71);  // Generates double version
maximum('a', 'z');    // Generates char version

You can explicitly specify the type when needed:

maximum<double>(5, 3.14);  // Forces double version

Templates support multiple type parameters:

template <typename T, typename U>
void printPair(T first, U second) {
    std::cout << first << ", " << second << std::endl;
}

printPair(42, "hello");  // T=int, U=const char*

Templates work with reference parameters for modifying original values:

template <typename T>
void swapValues(T& a, T& b) {
    T temp = a;
    a = b;
    b = temp;
}

Function templates provide compile-time polymorphism with zero runtime overhead, making them ideal for performance-critical generic code.

Try it yourself

#include <iostream>
#include "MathUtils.h"
using namespace std;

int main() {
    // Read inputs
    int a, b;
    double value, low, high;
    char ch;
    
    cin >> a;
    cin >> b;
    cin >> value;
    cin >> low;
    cin >> high;
    cin >> ch;
    
    // TODO: Use the minimum template to find min of two integers
    // Print: "Min of <a> and <b>: <result>"
    
    // TODO: Use the minimum template to find min of 'm' and input character
    // Print: "Min of m and <char>: <result>"
    
    // TODO: Use the clamp template on the double value
    // Print: "Clamp <value> to [<low>, <high>]: <result>"
    
    // TODO: Use the clamp template on the first integer with range [0, 100]
    // Print: "Clamp <value> to [0, 100]: <result>"
    
    // TODO: Use the swapValues template on the two integers
    // Print: "After swapValues: <a>, <b>"
    
    return 0;
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming