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<int>
,其包含了一个值为27的元素;
对于函数模板类型推导的规则来说,并不支持像auto这样自动适配{args...}
这种初始化列表的形式;
template<typename T>
void f(T param);
f({1,2,3}); // 编译错误!!!无法为T推导类型!!!
auto x{1,2,3}; // OK!!!
函数模板类型推导只能这样做:
template<typename T>
void f(std::initializer_list<T> 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<int> v;
...
auto resetV =
[&v](const auto& newValue){ v = newValue;};
...
resetV({1,2,3}); // 错误!!!
Things to Remember
- auto 类型推导跟模板类型推导一样,但auto能自然的支持std::initializer_list类型推导,而模板不行;
- 函数返回类型或lambda参数中的auto,表示模板类型推导,而不是auto类型推导;