您的位置:首页 > 编程语言 > C语言/C++

Effective.Modern.C++ 笔记 Item 1: Understand template type deduction

2015-02-02 10:58 721 查看
这一个条目讲的是以前尚未在 《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



可以看到 cx 和 rx虽然都具有const, 推导出来还是 为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


数组作为参数时的情况

数组在作为参数时大多数情况会decay 成pointer的情况,是C/C++ 程序员应该了解的。

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 (&)
) noexcept
{
return N;
}


当然,作为一个modern C++ coder, 作者提议使用C++11 STL中的array。

函数指针的类型推导和数组差不多。

最后依旧是Tings to remember

• During template type deduction, arguments that are references are treated as
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等利益网站的转载,否则追究到底!

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: