Skip to content
Theory · Templates · lesson 1 of 11

Function templates

The overloads twice(int) and twice(double) differ only in type, while their bodies are the same: return x * 2;. long and float would need two more copies of it. A function template writes the body once, and the compiler creates the versions for the needed types itself:

C++
#include <iostream>

template <typename T>
T twice(T x) {
    return x * 2;
}

int main() {
    std::cout << twice(21) << ' ' << twice(1.25) << '\n';  // 42 2.5
}

Template parameter

A function template is a blueprint from which the compiler builds ordinary functions. The line template <typename T> declares a template parameter T, a name that stands for a type. In the parameters, the return type and the body, T stands where an ordinary function would have int or double. The name T is only a convention: Value works too, and class may be written instead of typename.

Instantiation

For the call twice(21), the compiler substitutes int for T and gets the function int twice(int x). This is instantiation: a function for a specific type is created from the template. The call twice(1.25) creates a second function, double twice(double x). Another call with an int uses the version already created.

The compiler checks the template's body separately for each type. For int and double, the expression x * 2 is valid. But a std::string cannot be multiplied by 2, so the call twice(std::string("ab")) does not compile, even though the template itself is correct.

Templates in headers

To create the int version, the compiler needs the template's body; a declaration alone is not enough. That is why the whole template, body included, usually goes in the header twice.h:

C++
#pragma once

template <typename T>
T twice(T x) {
    return x * 2;
}

If two .cpp files include such a header, an ordinary function defined in it causes a multiple definition error. A template does not. The one definition rule allows identical definitions of a template in different translation units, as it does for inline functions.

Common mistake

The template is split like an ordinary function: twice.h keeps the declaration template <typename T> T twice(T x);, and the body moves to twice.cpp. Both files compile, but the build clang++ main.cpp twice.cpp fails:

C++
#include <iostream>
#include "twice.h"

int main() {
    std::cout << twice(21) << '\n';  // ✗
}
TEXT
undefined reference to `int twice<int>(int)'

This message comes from the linker; in the course exercises it reads undefined symbol. twice.cpp has no call with an int, so the int version is not created there. main.cpp has no body of the template, so the version cannot be created there either. Move the body into twice.h.