Template Generic Syntax
template<typename T>
void f(ParamType param);
f(expr);
Case 1: ParamType
is a Reference or Pointer, but not a Universal or Forward Reference. In this case type deduction works this way. The compiler ignores the reference part if it exists in expr
. The compiler then pattern-matches expr
's type against ParamType
to determing T
.
template<typename T>
void f(T& param); //param is a reference
int x = 27; // x is an int
const int cx = x; // cx is a const int
const int& rx = x; // rx is a reference to x as a const int
f(x); // T is int, param's type is int&
f(cx); // T is const int, param's type is const int&
f(rx); // T is const int, param's type is const int&
Case 2: ParamType
is a Universal Reference or Forward Reference. In this case type deduction is the same as in case 1 if the expr
is an rvalue. If expr
is an lvalue, both T
and ParamType
are deduced to be lvalue references.
template<typename T>
void f(T&& param); // param is a universal reference
int x = 27; // x is an int
const int cx = x; // cx is a const int
const int& rx = x; // rx is a reference to x as a const int
f(x); // x is lvalue, so T is int&, param's type is also int&
f(cx); // cx is lvalue, so T is const int&, param's type is also const int&
f(rx); // rx is lvalue, so T is const int&, param's type is also const int&
f(27); // 27 is rvalue, so T is int, param's type is therefore int&&
Case 3: ParamType
is Neither a Pointer nor a Reference. If expr
is a reference the reference part is ignored. If expr
is const that is ignored as well. If it is volatile that is also ignored when deducing T's type.
template<typename T>
void f(T param); // param is now passed by value
int x = 27; // x is an int
const int cx = x; // cx is a const int
const int& rx = x; // rx is a reference to x as a const int
f(x); // T's and param's types are both int
f(cx); // T's and param's types are again both int
f(rx); // T's and param's types are still both int