[Effective Modern C++] Item 2. Understand auto type deduction

条款二 了解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 = 27; // uref3 -> int&&

// case 3
auto x = 27; // 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 = 27; // x1 -> int
auto x2(27); // x2 -> int
auto x3 = {27}; // x3 -> std::initializer_list<int>
auto x4{27}; // x4 -> std::initializer_list<int>

列表初始化是auto与template类型推断的唯一区别,template函数推断中不能使用列表形式的初始化{}

auto x = {11, 23, 9};
template<typename T>
void f(T param);
f({11, 23, 9}); // wrong!

template<typename T>
void f(std::initializer_list<T> initList);
f({11, 23, 9}); // T -> int, initList -> std::initializer_list<int>

C+14可以使用auto来推断函数返回类型,并且lambda可以在形参声明中使用auto,但是此处的auto使用template类型推断而非auto类型推断,所以返回列表初始化将报错

auto createInitList() {
    return {1, 2, 3};
} // error!

std::vector<int> v;
auto resetV = [&v](const auto& newValue) {v = newValue};
resetV({1, 2, 3}) // error!

总结

  • auto类型推断总是和template类型推断一样,但是auto类型推断把列表初始化解析成std::initializer_list,template类型推断则不然
  • 在函数返回类型以及lambda形参中的auto,采用template类型推断而非auto类型推断
原文地址:https://www.cnblogs.com/Azurewing/p/4723210.html