本文章属于专栏《业界Cpp进阶建议整理》
本文列出《Effective Modern C++》的1-5条的个人理解的极精简版本。
- Item1、模版类型推导
- 个人理解:推导规则是繁琐的,和运算符优先级一样,背下来没有意义,最好的办法是在使用中熟悉。常用的推导结果如下表1。目前没有一个完全正确的打印推导结果工具(这是模板使用和调试困难的核心原因之一,个人觉得这是未来c++标准委员会设计时必须要考虑改进的点),所以要么深刻理解推导规则,要么使用别人建立的推导结果表,对大部分人,我的建议是后者。
- 表1
P A T 1 T int int 2 T int* int* 3 T int& int 4 T const int int 5 T const int * const int * 6 T int * const int * 7 T const int & int 8 T const int * const const int * 9 T char [2] char * 10 T const char [12] const char * 11 T void (int) void (*)(int) 12 const T int int 13 const T int * int * 14 const T int & int 15 const T const int int 16 const T const int * const int * 17 const T const int & int 18 const T const int * const const int * 19 const T char [2] char * 20 const T const char [12] const char * 21 const T void (int) void (*)(int) 22 T& int int 23 T& int * int * 24 T& int & int 25 T& const int const int 26 T& const int * const int * 27 T& const int & const int 28 T& const int * const const int * const 29 T& char [2] char [2] 30 T& const char [12] const char [12] 31 T& void (int) void (int) 32 T&& int int & 33 T&& int * int *& 34 T&& int & int & 35 T&& const int const int & 36 T&& const int * const int *& 37 T&& const int & const int & 38 T&& const int * const const int * const & 39 T&& char [2] char (&)[2] 40 T&& const char [12] const char (&)[12] 41 T&& void (int) void (&)(int) 42 T&& int && int 43 const T& int && int
- Item2、理解auto类型推导
- auto的推导与模版的推导方式只有一个不同,auto可以推导出std::initializer_list,模版推导不行。
- 另外注意auto在c++11中不能用于返回值推导,但是c++14可以,但是返回值不可被推导为std::initializer_list
- Item3、理解decltype
- 返回名字或者表达式类型,它不会丢掉引用。
- 下图是容易理解的推导结果
- 想用decltype在模版中表示返回值类型
- 这里需要注意几个点
- 输入参数是Container&&,这里使用了通用引用,是为了函数传入参数可以是左值引用,也可以是右值引用
- 这里需要注意几个点
- 在c++14中,想在auto推导时,不丢掉引用,就用decltype(auto)
- decltype陷阱
- decltype对于表达式,会把类型定义为返回类型的引用。在c++11中。int x; x是变量,(x)是表达式,所以decltype(x)返回int,decltype((x))返回int&。特别小心不要返回局部变量的引用
- decltype对于表达式,会把类型定义为返回类型的引用。在c++11中。int x; x是变量,(x)是表达式,所以decltype(x)返回int,decltype((x))返回int&。特别小心不要返回局部变量的引用
- Item4、查看类型推导的结果
- 通过编译器报错
- 通过运行时输出
- 使用typeid(T).name。但是这里会像传值一样推导,会丢掉引用、const、volatile部分
- Boost.TypeIndex是更好的选择
- 注意,目前所有的工具都可能出现问题,目前只有深刻理解推导规则或者看已有的推导结果表