条款一 了解模板类型推断 基本情况 首先定义函数模板和函数调用的形式如下,在编译期间,编译器推断T和ParamType的类型,两者基本不相同,因为ParamType常常包含const.引用等修饰符 template<typename T> void f(ParamType param); // 函数模板形式 f(expr); // 函数调用 存在T的类型即为expr类型的情况,如下T为int templat<typename T> void f(const T& param…
条款二 了解auto类型推断 基础知识 除了一处例外,auto的类型推断与template一样.存在一个直接的从template类型推断到auto类型推断的映射 三类情况下的推断如下所示: // case 1 const auto& rx = x; // rx -> int // case 2 auto&& uref1 = x; // uref1 -> int& auto&& uref2 = cx; // uref2 -> const in…
条款三 了解decltype 基础知识 提供一个变量或者表达式,decltype会返回其类型,但是返回的内容会使人感到奇怪. 以下是一些简单的推断类型: ; // decltype(i) -> const int bool f(const Widget& w); // decltype(w) -> const Widget&, decltype(f) -> bool(const Widget&) struct Point { int x, y; } // decl…
理解模板类型推断(template type deduction) 我们往往不能理解一个复杂的系统是如何运作的,但是却知道这个系统能够做什么.C++的模板类型推断便是如此,把参数传递到模板函数往往能让程序员得到满意的结果,但是却不能够比较清晰的描述其中的推断过程.模板类型推断是现代C++中被广泛使用的关键字auto的基础.当在auto上下文中使用模板类型推断的时候,它不会像应用在模板中那么直观,所以理解模板类型推断是如何在auto中运作的就很重要了. 下面将详细讨论.看下面的伪代码: templ…
条款6 当推断意外类型时使用显式的类型初始化语句 基础知识 当使用std::vector<bool>的时候,类型推断会出现问题: std::vector<bool> features(const Widget& w); // OK ]; processWidget(w, highPriority); // ERROR auto highPriority = features(w)[]; processWidget(w, highPriority); // undefined…
条款四 知道如何看待推断出的类型 基础知识 有三种方式可以知道类型推断的结果: IDE编辑器 编译器诊断 运行时输出 使用typeid()以及std::type_info::name可以获取变量的类型信息,但是存在一些问题,代码如下: template<typename T> void f(const T& param) { using std::cout; cout << "T = " << typeid(T).name() <<…
条款2: 理解auto自己主动类型推导 假设你已经读过条款1关于模板类型推导的内容,那么你差点儿已经知道了关于auto类型推导的所有. 至于为什么auto类型推导就是模板类型推导仅仅有一个地方感到好奇.那是什么呢?即模板类型推导包含了模板.函数和參数,而auto类型判断不用与这些打交道. 这当然是真的.可是没关系. 模板类型推导和auto自己主动类型推导是直接匹配的. 从字面上看,就是从一个算法转换到还有一个算法而已. 在条款1中.阐述模板类型推导採用的是常规的函数模板: template<ty…
条款5 相对显式类型声明,更倾向使用auto 基础知识 auto能大大方便变量的定义,可以表示仅由编译器知道的类型. template<typename It> void dwim(It b, It e) { while(b != e) { //typename std::iterator_traits<It>::value_type currValue = *b; // old type auto currValue = *b; // new type } } auto可以用来定…
假设有一个接收universal references的模板函数foo,定义如下: template<typename T> void foo(T&& t) { cout << "foo(T&& t)" << endl; } 如果想对某些类型做特殊处理,写一个重载版本的foo,比如想对float类型做特殊处理,就写一个接收float类型的foo: void foo(float n) { cout << &q…
条款7 辨别使用()与{}创建对象的差别 基础知识 目前已知有如下的初始化方式: ); ; }; }; // the same as above 在以“=”初始化的过程中没有调用赋值运算,如下例所示: Widget w1; // default ctor Widget w2 = w1; // copy ctor w1 = w2; // assignment, operator = 还可以用来初始化: class Widget { }; // fine ; // fine ); // error…