template<typenameT>voidf(T¶m);// param is a reference
intx=27;// x is an int
constintcx=x;// cx is a const int
constint&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&
param is const T&
1
2
3
4
5
6
7
8
9
10
template<typenameT>voidf(constT¶m);// param is now a ref-to-const
intx=27;constintcx=x;constint&rx=x;f(x);// T is int, param's type is const int&
f(cx)// T is int, param's type is const int&
f(rx);// T is int, param's type is const int&
param is T*
1
2
3
4
5
6
7
8
9
template<typenameT>voidf(T*param);// param is now a pointer
intx=27;// as before
constint*px=&x;// px is a ptr to x as a const int
f(&x);// T is int, param's type is int*
f(px);// T is const int,
// param's type is const int*
param is T&&
If expr is an lvalue, both T and ParamType are deduced to be lvalue references.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template<typenameT>voidf(T&¶m);// param is now a universal reference
intx=27;constintcx=x;constint&rx=x;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&&
param is T
That means that param will be a copy of whatever is passed in—a completely new
object.
1
2
3
4
5
6
7
8
9
10
template<typenameT>voidf(Tparam);// param is now passed by value
intx=27;constintcx=x;constint&rx=x;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
Array Arguments
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
constcharname[]="J. P. Briggs";// name's type is
// const char[13]
constchar*ptrToName=name;// array decays to pointer
template<typenameT>voidf(Tparam);// template with by-value parameter
f(name);// name is array, but T deduced as const char*
/*********second condition***********/template<typenameT>voidf(T¶m);// template with by-reference parameter
f(name);// pass array to f, T is const char [31], param is const char (&)[13]
1
2
3
4
5
6
7
8
9
10
11
// return size of an array as a compile-time constant. (The
// array parameter has no name, because we care only about
// the number of elements it contains.)
template<typenameT,std::size_tN>constexprstd::size_tarraySize(T(&)[N])noexcept{returnN;}intkeyVals[]={1,3,7,9,11,22,35};intmappedVals[arraySize(keyVals)];
Function Arguments
1
2
3
4
5
6
7
8
9
10
11
12
13
voidsomeFunc(int,double);// someFunc is a function;
// type is void(int, double)
template<typenameT>voidf1(Tparam);// in f1, param passed by value
template<typenameT>voidf2(T¶m);// in f2, param passed by ref
f1(someFunc);// param deduced as ptr-to-func;
// type is void (*)(int, double)
f2(someFunc);// param deduced as ref-to-func;
// type is void (&)(int, double)
auto type deduction is usually the same as template type deduction, but auto type deduction assumes that a braced initializer represents a std::initial
izer_list, and template type deduction doesn’t. auto in a function return type or a lambda parameter implies template type deduction, not auto type deduction.