【Effective modern C++ 提炼】《类型推导》- Item2:《auto的类型推导》

        • aoto与函数模板的参数类型推导相似的推导规则
        • aoto与函数模板的参数类型推导的不同之处
        • 当auto用于函数的返回,以及lambda参数时
        • Things to Remember

aoto与函数模板的参数类型推导相似的推导规则

相比于“函数模板类型推导”

template<typename T>
void f(ParamType);

f(expr);

当通过auto声明一个变量时,auto跟模板中的T扮演着相同的角色,而变量的类型说明符充当着模板的ParamType的作用;

auto x = 27;        // 类型说明符就是 auto本身
const auto cx = x;  // 类型说明符就是 const auto
const auto& rx = x; // 类型说明符就是 const auto&

跟函数模板的类型推导一样,auto类型的推导也分为3个case:

Case1. 类型说明符是一个指针/引用(而不是通用引用)

int x = 27;
const auto& rx = x; // const int&

Case2. 类型说明符为通用引用时

int x = 27;
const int cx = 27;

auto&& uref1 = x;   // x是一个左值 , uref1's type => int&
auto&& uref2 = cx;  // cx是一个const左值 , uref2's type => const int&
auto&& uref3 = 27;  // 27是一个右值 , uref3's type => int&&

Case3. 类型说明符既不是指针,也不是引用

auto x = 27;        // x'type => int
const auto cx = x;  // x'type => const int

对于函数与数组

 const char name[] = "abc";

 auto arr1 = name;  // arr1'type => const char*
 auto& arr2 = name; // arr2'type => const char(&)[4]

-------------
void someFunc(int,double);

auto func1 = someFunc;  // func1'type => void(*)(int,double)
auto& func2 = someFunc; // func2'type => void(&)(int,double)

aoto与函数模板的参数类型推导的不同之处

C++ 11 新加了一种初始化值得方式,如下:

int x1 = 27;
int x2(27);

int x3 = {27};
int x4{27};

四种语法,但结果都是一样的,即创建一个int类型变量;
同样,这种语法适用于auto:

auto x1 = 27;
auto x2(27);

auto x3 = {27};
auto x4{27};

但,这两类初始化语法的意义是不同的,使用{args...}定义的变量,其类型实际上是std::initializer_list,其包含了一个值为27的元素;

对于函数模板类型推导的规则来说,并不支持像auto这样自动适配{args...}这种初始化列表的形式;

template<typename T>
void f(T param);

f({1,2,3}); // 编译错误!!!无法为T推导类型!!!

auto x{1,2,3}; // OK!!!

函数模板类型推导只能这样做:

templateT>
void f(std::initializer_list initList);

f({1,2,3}); // 没问题!!!

所以,auto 跟 函数模板类型推导 的真正区别,便是auto天然支持std::initializer_list{args...}初始化方式,而函数模板不行;

当auto用于函数的返回,以及lambda参数时

C++ 14
auto用于函数声明的返回类型时,表示返回值可被推导;
但是,并不支持自然推导std::initializer_list,即以{args...}形式返回;此处,auto提供的是“支持模板类型推导,而非auto类型推导”;

auto createInitList()
{
    int a = 27;
    return a;       // 返回int类型
}

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

auto也能用于lambda表达式的参数,同样,它所表示的是参数支持“函数模板类型推导”,而不是auto类型推导;所以,也不支持initializer_list{args...}自然推导;

std::vector v;
...
auto resetV =
 [&v](const auto& newValue){ v = newValue;};
...
resetV({1,2,3});    // 错误!!!

Things to Remember

  • auto 类型推导跟模板类型推导一样,但auto能自然的支持std::initializer_list类型推导,而模板不行;
  • 函数返回类型或lambda参数中的auto,表示模板类型推导,而不是auto类型推导;

你可能感兴趣的:(C/C++/C#)