Consider the following example that shows what comes into our mind if we want to use function templates with multiple files.
main.cpp
template <typename T, typename U>
auto max(T a, U b);
max(1, 2);lib.cpp
template <typename T, typename U>
auto max(T a, U b)
{
return a < b ? b : a;
}But it does not work. Why it does not work? Let’s think…
Compiler compiles main.cpp, it does see the forward declaration. It is good with that. Compiler then compiles lib.cpp with no problem.
But when it comes to linking, linker cries as it could not find definition for max<int, int>(int, int). Why it could not find? Because max<int, int>(int, int) has not been invoked in lib.cpp. And we know that unless templated function is invoked in a translation unit, compiler does not create function instance.
It should be clear now. Well, how do we use function templates with multi files? We can use header files.
lib.h
#ifndef LIB_H
#define LIB_H
template <typename T, typename U>
auto max(T a, U b)
{
return a < b ? b : a;
}
#endifmain.cpp
#include "lib.h"
max(1, 2);Now it should work. We must think the case if we include lib.h in multiple files. Should it violet ODR? Well, no. ODR allows us to have multiple definitions of templates. Moreover, the function instances are created are implicitly inline. So, there can be multiple definitions of function instances.