Function Templates
Basic syntax
basic_template.cpp
#include <iostream>
template <typename T>
T maxValue(T a, T b) {
return (a > b) ? a : b;
}
int main() {
std::cout << maxValue(10, 20) << std::endl; // T = int
std::cout << maxValue(3.5, 1.2) << std::endl; // T = double
return 0;
}Template argument deduction
Explicit instantiation
Occasionally you need to be explicit — for example, when the argument types don't match and deduction would be ambiguous, or when you want to force a particular type. You can supply the template argument directly with angle brackets:
explicit_instantiation.cpp
#include <iostream>
template <typename T>
T maxValue(T a, T b) {
return (a > b) ? a : b;
}
int main() {
// Without <int>, this would fail: deduction can't decide
// between T = int and T = double from mismatched arguments.
std::cout << maxValue<int>(3, 5.9) << std::endl; // forces T = int, prints 5
// Explicitly requesting double even though both args are int literals.
std::cout << maxValue<double>(3, 5) << std::endl;
return 0;
}Multiple template parameters
A template can take more than one type parameter, which is useful when the function needs to combine or relate two different types.
multiple_params.cpp
#include <iostream>
template <typename T, typename U>
void printPair(T first, U second) {
std::cout << "(" << first << ", " << second << ")" << std::endl;
}
int main() {
printPair(1, "one"); // T = int, U = const char*
printPair(3.14, 'a'); // T = double, U = char
return 0;
}What you can put in a template body
Any operation the compiler can validate once
Tis known — arithmetic, comparisons, member access, and so on.A template only fails to compile for a given type if that type doesn't support an operation actually used inside it (this is related to a principle called SFINAE, and later refined by C++20 concepts).
You can mix template and non-template parameters in the same function.