第四章-新手易学老兵易用
4.1 右尖括号>的改进
使用模板时,会加上下文判断,不会识别成右移操作符
4.2 auto类型推导
- 重新实现auto的语义
- auto声明变量的类型必须由编译器在编译时期推导
- auto声明的变量必须被初始化
- auto优势
- 简化代码,迭代器类型定义很长的时候可以用
- 避免一些在类型声明时的错误,隐式转换
- 一定程度上支持泛型的编程
TODO auto 与 const 去除cv语义?
4.3 decltype
- typeid(a).name()
- 简化代码,比如迭代器
typedef decltype(vec.begin()) vectype,看起来跟auto非常类似,也类似于是一种“占位符”式的替代 - 重用匿名类型,比如匿名结构体
- 在模板中的作用
4.3.3 decltype推导四规则
- 如果e是一个没有带括号的标记符表达式(id-expression)或者类成员访问表达式,那么decltype(e)就是e所命名的实体的类型。此外,如果e是一个被重载的函数,则会导致编译时错误。
- 否则,假设e的类型是T,如果e是一个将亡值(xvalue),那么decltype(e)为T&&。
- 否则,假设e的类型是T,如果e是一个左值,则decltype(e)为T&。
- 否则,假设e的类型是T,则decltype(e)为T。
第一点和第三点需要注意
4.3.4 cv限制符的继承与冗余的符号
- decltype能够表示表达式的cv限制符(易变的,不变的)的。但是如果对象的定义中有const或volatile限制符,使用decltype进行推导时,其成员不会继承const或volatile限制符
int i = 1; int &j = 1; decltype(j) &var2 = i; // var2有冗余的&,会被忽略
4.4 追踪返回类型
4.4.1 追踪返回类型的引入
使用
template<typename T1, typename T2>
auto sum(const T1 &a, const T2 &b)->decltype(a + b) {
return a + b;
}
double ret = sum<int, double>(10, 2.5);
4.4.2 使用追踪返回类型的函数
-
可以省略作用域
class TestNameSpaceTestNameSpace { public: struct TestT {int b;}; TestT data_; TestT getb(); }; // TestNameSpaceTestNameSpace::TestT TestNameSpaceTestNameSpace::getb() { // return data_; // } // 可以不用写 TestNameSpaceTestNameSpace::TestT auto TestNameSpaceTestNameSpace::getb()->TestT { return data_; } -
模板中的一些类型推导 整个例子中没有看到一个“具体”的类型声明。
// 同 4.4.1 例子 template<typename T1, typename T2> auto sum(const T1 &a, const T2 &b)->decltype(a + b) { return a + b; } double ret = sum<int, double>(10, 2.5); -
简化函数的定义,提高代码的可读性,函数指针
int (*p1)(int a); auto (*p2)(int a)->int; -
转发函数 用了追踪返回类型,可以实现参数和返回类型不同时的转发
4.5 基于范围的for循环
for (const auto &i : vec) {}