条款二 了解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 int&
auto&& uref3 = ; // uref3 -> int&& // case 3
auto x = ; // x -> int
const auto cx = x; // x -> int
对于数组和函数,有如下推断:
const char name[] = "R. N. Briggs";
auto arr1 = name; // arr1 -> const char*
auto& arr2 = name; // arr2 -> const char(&)[13] void someFunc(int, double);
auto func1 = someFunc; // func1 -> void (*)(int, double)
auto& func2 = someFunc; // func2 -> void (&)(int, double)
但是在使用初始化列表(std::initializer_list)的情况下,auto的类型推断会有问题
auto x = ; // x1 -> int
auto x2(); // x2 -> int
auto x3 = {}; // x3 -> std::initializer_list<int>
auto x4{}; // x4 -> std::initializer_list<int>
列表初始化是auto与template类型推断的唯一区别,template函数推断中不能使用列表形式的初始化{}
auto x = {, , };
template<typename T>
void f(T param);
f({, , }); // wrong! template<typename T>
void f(std::initializer_list<T> initList);
f({, , }); // T -> int, initList -> std::initializer_list<int>
C+14可以使用auto来推断函数返回类型,并且lambda可以在形参声明中使用auto,但是此处的auto使用template类型推断而非auto类型推断,所以返回列表初始化将报错
auto createInitList() {
return {, , };
} // error! std::vector<int> v;
auto resetV = [&v](const auto& newValue) {v = newValue};
resetV({, , }) // error!
总结
- auto类型推断总是和template类型推断一样,但是auto类型推断把列表初始化解析成std::initializer_list,template类型推断则不然
- 在函数返回类型以及lambda形参中的auto,采用template类型推断而非auto类型推断