这一个条目讲的是以前尚未在 《Effective C++》系列中讲的C++的模板的类型推导。
第一个条目就是模板,其对于现代C++的重要性不言自喻。
书中先写出伪代码,以供下列使用。
template<typename T>
void f(ParamType param);
ParamType 代表推导出的类型。
调用:
f(expr);
OK, 下面开始正餐:
C++ 模板的类型推导分三种情况
Case 1: 当 ParamType 为 T& 或者 const T&
模板函数声明如下时候:
template<typename T>
void f(T& param); // param is a reference
类型推导会执行以下工作
1. 当调用时传入的expr 为引用时, 忽略引用部分。
2. 然后模式匹配 expr 与 ParamType。
例子:
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&
f(x)的推导结果很自然,而f(cx) 和 f(rx) 则是语言本身为了保持传入参数的不可变性, 也就是const 属性。cx和 rx 都是 具有const属性的类型,自然当做实参引用传递时后也要加 const 喽。: )
ParamTye 为 const T& 时:
template<typename T>
void f(const T& param); // param is now a ref-to-const
int x = 27;
const int cx = x;
const int& 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&
x 传入时, ParamType 类型被推导为const int&。
Case 2:ParamType 为 Universal Reference(T&&) 时
当模板函数声明如下时候:
template<typename T>
void f(T&& param); // param is now a universal reference
&&是C++ 11 中引入的新符号。
例子如下:
template<typename T>
void f(T&& param); // param is now a universal refernce
int x = 27;
const int cx = x;
const int& 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&&
作者在书中将详细情况到ITEM 24.。
其实就是C++11 中的右值引用与左值引用的叠加原则。
具体可以google或者百度,许多文章都解释的很详细。
Case 3: ParamType is 不是指针也不是引用(也就是值了)
template<typename T>
void f(T param); // param is now passed by value
类型推导过程:1.判断 expr 是否为引用,若是, 忽略引用部分。
2.如果 expr 为const, volatile ,忽略这些。
int x = 27;
const int cx = x;
const int& 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
但是当传入的是const pointer的时候,为了防止通过复制的pointer改变相对应的值 ,推导出的为 const pointer。
template<typename T>
void f(T param); // param is still passed by value
const char* const ptr =
"Fun with pointers"; // ptr is const pointer to const object
f(ptr); // pass arg of type const char * const
数组作为参数时的情况
const char name[] = "J. P. Briggs"; // name's type is
// const char[13]
const char * ptrToName = name; // array decays to pointer
template<typename T>
void f(T param);<span style="white-space:pre"> </span>// template with by-value parameter
f(name) 等效于 f(ptrToName)
template<typename T>
void f(T& param); // template with by-reference parameter
f(name); // pass array to f
f函数获取到的是数组而不是指针,也就是可以在f函数中通过sizeof获取数组的长度信息。
template<typename T, std::size_t N>
// see info
constexpr std::size_t arraySize(T (&)[N]) noexcept
{
return N;
}
当然,作为一个modern C++ coder, 作者提议使用C++11 STL中的array。
non-references, i.e., their reference-ness is ignored.
• When deducing types for universal reference parameters, lvalue arguments get
special treatment.
• When deducing types for by-value parameters, const and/or volatile argu‐
ments are treated as non-const and non-volatile.
• During template type deduction, arguments that are array or function names
decay to pointers, unless they’re used to initialize references.
此文章可经本人同意后转载,谢绝百度以及360等利益网站的转载,否则追究到底!