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

来源:互联网 发布:华为面试经验知乎 编辑:程序博客网 时间:2024/05/21 08:12

这一个条目讲的是以前尚未在 《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 referenceint x = 27;                    // x is an intconst int cx = x;             // cx is a const intconst 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-constint 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 refernceint 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 intf(cx);                   // T's and param's types are again both intf(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 valueconst char* const ptr ="Fun with pointers";                     // ptr is const pointer to const objectf(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 parameterf(name);                         // pass array to f



f函数获取到的是数组而不是指针,也就是可以在f函数中通过sizeof获取数组的长度信息。
下列函数很常见:

template<typename T, std::size_t N>// see infoconstexpr std::size_t arraySize(T (&)[N]) 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等利益网站的转载,否则追究到底!





0 0
原创粉丝点击