Function template
A function template defines a family of functions.
Contents |
[edit] Syntax
template < parameter-list > declaration
|
|||||||||
[edit] Explanation
declaration defines or declares a class (including struct and union), a member class or member enumeration type, a function or member function, a static data member of a class template, or a type alias. It may also define a template specialization. This page focuses on function templates.
parameter-list is a non-empty comma-separated list of the template parameters, each of which is either non-type parameter, a type parameter, a template parameter, or a parameter pack of any of those. For function templates, template parameters are declared in the same manner as for class templates: see class template page for details.
[edit] Function template instantiation
A function template by itself is not a type, or a function, or any other entity. No code is generated from a source file that contains only template definitions. In order for any code to appear, a template must be instantiated: the template arguments must be determined so that the compiler can generate an actual function (or class, from a class template).
[edit] Explicit instantiation
template return-type name < argument-list > ( parameter-list ) ;
|
(1) | ||||||||
template return-type name ( parameter-list ) ;
|
(2) | ||||||||
extern template return-type name < argument-list > ( parameter-list ) ;
|
(3) | (since C++11) | |||||||
extern template return-type name ( parameter-list ) ;
|
(4) | (since C++11) | |||||||
An explicit instantiation definition forces instantiation of the function or member function they refer to. It may appear in the program anywhere after the template definition, and for a given argument-list, is only allowed to appear once in the program.
An explicit instantiation declaration (an extern template) prevents implicit instantiations: the code that would otherwise cause an implicit instantiation has to use the explicit instantiation definition provided somewhere else in the program.
template<typename T> void f(T s) { std::cout << s << '\n'; } template void f<double>(double); // instantiates f<double>(double) template void f<>(char); // instantiates f<char>(char) template void f(int); // instantiates f<int>(int)
[edit] Implicit instantiation
When code refers to a function in context that requires the function definition to exist, and this particular function has not been explicitly instantiated, implicit instantiation occurs. The list of template arguments does not have to be supplied if it can be deduced from context
#include <iostream> template<typename T> void f(T s) { std::cout << s << '\n'; } int main() { f<double>(1); // instantiates and calls f<double>(double) f<>('a'); // instantiates and calls f<char>(char) f(7); // instantiates and calls f<int>(int) void (*ptr)(std::string) = f; // instantiates f<string>(string) }
Note: omitting <>
entirely allows overload resolution to examine both template and non-template overloads.
[edit] Template argument deduction
In order to instantiate a function template, every template argument must be known, but not every template argument has to be specified. When possible, the compiler will deduce the missing template arguments from the function arguments. This occurs when a function call is attempted and when an address of a function template is taken.
template<typename To, typename From> To convert(From f); void g(double d) { int i = convert<int>(d); // calls convert<int,double>(double) char c = convert<char>(d); // calls convert<char,double>(double) int(*ptr)(float) = convert; // instantiates convert<int, float>(float) }
This mechanism makes it possible to use template operators, since there is no syntax to specify template arguments for an operator other than by re-writing it as a function call expression.
Template argument deduction takes place after the function template name lookup (which may involve argument-dependent lookup) and before overload resolution.
For each function parameter of type P
specified in the function template, the compiler examines the corresponding function call argument of type A
as follows:
- If
P
is a (possibly cv-qualified, possibly reference to) std::initializer_list<Q> and the function call argument is a brace-enclosed list of initializers, argument deduction is attempted between the typeQ
and each element of the braced-init-list, which all must match
template<class Q> void f(std::initializer_list<Q>); int main() { f({1,2,3}); // OK: calls void f(initializer_list<int>) // f({1,"asdf"}); // error: Q can't be both int and const char* }
- Otherwise, if the function call argument is a braced-init-list, the type cannot be deduced and must be specified
template<class T> void f(T); int main() { // f({1,2,3}); // error: T cannot be deduced from a braced-init-list f<std::vector<int>>({1,2,3}); // OK, T is specified }
- If the function template ends with a parameter pack, each remaining argument is compared with the type of the parameter pack and each comparison deduces the next type in the expansion.
template<class H, class ...Tail> void f(H, Tail...); int main() { int x; double y; char z; f(x, y, z); // H = int, Tail = {double, char} }
- If a function template has a parameter pack that is not at the end of its parameter declaration list, the pack is not deducible and must be specified, along with all the types that follow (unless there are default parameters).
template<class... pack1, class T> void f1(T n, pack1... args) {} template<class... pack1, class T> void f2(pack1... args, T n) {} template<int...> struct T {}; template<int... pack1, int N, int... pack2> void g1(const T<N, pack1...>& arg1, const T<N, pack2...>&) {} template<int... pack1, int N, int... pack2> void g2(const T<pack1..., N>& arg1, const T<N, pack2...>&) {} int main() { f1(1,2,3,4); // okay, N=1, pack1={2,3,4} // f2(1,2,3,4); // error: parameter pack in f2's parameter list is not last T<1,2> t1; T<1,-1,0> t2; g1(t1, t2); // okay, N=1, pack1 = {2}, pack2={-1,0} // g2(t1, t2); // error: parameter pack in g2's first argument's template // parameter list is not last }
- If
P
is a non-reference type,
-
- If
A
is an array type, the pointer to an element ofA
is used in place ofA
for deduction. - If
A
is a function type, the pointer to this function type is used in place ofA
for deduction. - Otherwise, if
A
is a cv-qualified type, then the top level cv-qualifiers are ignored for deduction
- If
#include <utility> #include <iostream> template <class T> void array_to_pointer(T) { static_assert(std::is_same<T, int*>::value, ""); } template <class T> void func_to_pointer(T) { static_assert(std::is_same<T, void(*)(int)>::value, ""); } template <class T> void cv_ignored(T) { static_assert(std::is_same<T, int>::value, ""); } void foo(int) {} int main() { int a[3]; static_assert(std::is_same<decltype(a), int[3]>::value, ""); array_to_pointer(a); // array to pointer conversion: T = 'int*' static_assert(std::is_same<decltype(foo), void(int)>::value, ""); func_to_pointer(foo); // function to pointer conversion: T = 'void(*)(int)' const int b = 13; static_assert(std::is_same<decltype(b), const int>::value, ""); cv_ignored(b); // cv-qualifier ignored: T = 'int' std::cout << "done\n"; }
- If
P
is a cv-qualified type, the top-level cv qualifiers are ignored for deduction. - If
P
is a reference type, the type referred to byP
is used for deduction. - If
P
is an rvalue reference to a cv-unqualified template parameter, and the corresponding function call argument is an lvalue, the type lvalue reference toA
is used in place ofA
for deduction (Note: this is the basis for the action of std::forward)
template <class T> int f(T&&); // P is rvalue reference to cv-unqualified T (special case) template <class T> int g(const T&&); // P is rvalue reference to cv-qualified T (not special) int main() { int i; int n1 = f(i); // argument is lvalue: calls f<int&>(int&) (special case) int n2 = f(0); // argument is not lvalue: calls f<int>(int&&) // int n3 = g(i); // error: deduces to g<int>(const int&&), which // // cant bind an rvalue reference to an lvalue: }
- After these transformations, the deduction process attempts to find such template arguments that would make
P
andA
identical, except that:
-
- If the original
P
is a reference type, the deducedA
(i.e., the type referred to by the reference) can be more cv-qualified than the transformedA
. - The transformed
A
can be another pointer or pointer to member type that can be converted to the deducedA
via a qualification conversions. - If
P
is a class andP
has the form simple-template-id, then the transformedA
can be a derived class of the deducedA
. Likewise, ifP
is a pointer to a class of the form simple-template-id, the transformedA
can be a pointer to a derived class pointed to by the deducedA
.
- If the original
#include <iostream> #include <utility> template<class T> void func_1(const T& t) { static_assert(std::is_same<T, bool>::value, ""); static_assert(std::is_same<decltype(t), const bool&>::value, ""); } template<class T> void func_2(volatile T* t) { static_assert(std::is_same<T, int>::value, ""); static_assert(std::is_same<decltype(t), volatile int*>::value, ""); } template<class T> class Foo {}; class Boo : public Foo<int> {}; template<template <class> class T1, class T2> void func_3(T1<T2>* t) { static_assert(std::is_same<T1<T2>, Foo<int>>::value, ""); static_assert(std::is_same<T2, int>::value, ""); static_assert(std::is_same<decltype(t), Foo<int>*>::value, ""); } int main() { bool a = false; static_assert(std::is_same<decltype(a), bool>::value, ""); // transformed A = 'bool' // deducted A can be more cv-qualified = 'const bool' func_1(a); int* b = nullptr; static_assert(std::is_same<decltype(b), int*>::value, ""); // transformed A = 'int*' // converted via qualification conversion to deducted A = 'volatile int*' func_2(b); Boo c; static_assert(std::is_same<decltype(&c), Boo*>::value, ""); // transformed A = 'Boo*' // can be a derived class, deducted A = 'Foo<int>*' func_3(&c); std::cout << "done\n"; }
- If
P
is a function type, pointer to function, or pointer to member function,
-
- If the argument is a set of overloaded functions that includes at least one function template, the parameter cannot be deduced.
- If the argument is a set of overloaded functions not containing function templates, template argument deduction is attempted with each overload. If only one succeeds, that successful deduction is used. If more than one succeeds, the template parameter cannot be deduced.
template <class T> int f(T (*p)(T)); int g(int); int g(char); // two overloads int main() { int i = f(g); // only one overload works: calls f(int (*)(int)) }
This section is incomplete Reason: The huge amount of stuff from 14.8.2.5. Except it will have to be made easy-to-follow somehow |
template<class T> struct Alloc {}; template<class T> using Vec = vector<T, Alloc<T>>; Vec<int> v; template<template<class,class> class TT> void g(TT<int, Alloc<int>>); g(v); // ok: deduces TT = vector template<template<class> class TT> void f(TT<int>); f(v); // error: TT cannot be deduced as "Vec" because Vec is an alias template
[edit] Template argument substitution
When a template argument is specified explicitly, but does not match the type of the corresponding function argument exactly, the template argument is adjusted by the following rules:
This section is incomplete |
[edit] Function template specialization
This section is incomplete Reason: note that there is a page for specializations in general, only function specifics go here: lack of partials, interaction with function overloads |
[edit] Overload resolution
To compile a call to a function template, the compiler has to decide between non-template overloads, template overloads, and the specializations of the template overloads.
template< class T > void f(T); // template overload template< class T > void f(T*); // template overload void f(double); // nontemplate overload template<> void f(int); // specialization of #1 f('a'); // calls #1 f(new int(1)); // calls #2 f(1.0); // calls #3 f(1); // calls #4
Note that only non-template and primary template overloads participate in overload resolution. The specializations are not overloads and are not considered. Only after the overload resolution selects the best-matching primary function template, its specializations are examined to see if one is a better match.
template< class T > void f(T); // overload #1 for all types template<> void f(int*); // specialization of #1 for pointers to int template< class T > void f(T*); // overload #2 for all pointer types f(new int(1)); // calls #2, even though #1 would be a perfect match
For detailed rules on overload resolution, see overload resolution