《Effective Modern C++》条款2
条款2:理解auto
类型推导(Understand auto
type deduction)
除了在一种情况下,auto
类型推导和模板类型推导是一样的。
在条款1中,使用以下统一的函数模板:1
2template<typename T>
void f(ParamType param);
和统一调用方式:1
f(expr);
在函数是f
的调用过程中,编译器使用expr
来推断T
和ParamType
。
当一个变量使用auto
来声明时,auto
扮演了模板中T
的角色,且该变量的类型说明符扮演了ParamType
的角色。因此,同条款1中一样,根据变量的类型说明符的形式分三种情况:
- 情况1:类型说明符是一个引用或指针,但不是一个万能引用(Universal Reference)
- 情况2:类型说明符是一个万能引用(Universal Reference)
- 情况3:类型说明符既不是指针也不是引用
这三种情况于条款1中的三种情况一一对应。
1 | auto x = 27; // x is int |
auto
类型推导和模板类型推导的不同之处在于:
如果一个auto
声明的变量使用花括号初始化,其推断的类型是一个std::initializer_list
的实例(模板实例)。但,如果把该花括号初始化传入到相应的模板中,类型推断将会失败,代码不会通过编译。
1 | auto x = {11, 23, 9}; // x is std::initializer_list<int> |
不过,可以指定模板的param
是一个std::initializer_list<T>
,模板类型推断就能推断出T
。
1 | template<typename T> |
对于C++14
,还有一点应该注意的是:
auto
作为函数返回值和lambda
的参数声明时,应该使用模板类型推导,而不是auto
类型推导。因此,下面的示例将不会通过编译。
1 | auto createInitList() |
要点:
- 通常情况下,
auto
类型推导和模板类型推导是一样的,但是auto
类型推导假定花括号初始化代表一个std::initializer_list
,而模板类型推导不会这样做。 - 在函数返回值或
lambda
参数中的auto
意味着模板类型推导,而不是auto
类型推导。