auto 类型推导就是模板类型推导,只有一个例外;关于模板类型推导参考这篇文章, 当一个变量被声明为auto ,auto相当于模板中的T ,而对变量做的相关的类型限定就像ParamType
例如:
auto nTmp = 100; // 符合第3种情况
const auto nConstTmp = nTmp; // 没有符合的一种情况
const auto& nConstRefTmp = nTmp; // 非通用引用
auto&& uref1 = nTmp; // nTmp是int并且是左值所以uref1的类型是int&
auto&& uref2 = nConstTmp; // nConstTmp是int并且是左值所以uref2的类型是const int&
auto&& uref3 = 100; // 100是int并且是右值所以uref3的类型是int&&
在非引用类型声明里,数组和函数名称如何退化成指针。这在 auto 类型推导上面也是一样:
const char name[] = "zhangsan"; // name的类型是const char[8];
auto arr1 = name; // arr1的类型是const char*
auto& arr2 = name; // arr2的类型是const char (&)[8]
void ProcessFun(int nParam);
auto& func1 = ProcessFun; // func1的类型是void (&)(int)
auto类型推导唯一一个与模板类型推导不同的地方就是在大括号{}的使用上,关于大括号的使用可以参考这篇文章
auto init1 = {100}; // 类型是std::intializer_list<int> 值是{ 100 }
auto init2{100}; // 同上
对待大括号初始化的行为是auto唯一和模板类型推导不一样的地方。当 auto 声明变量被使用一对大括号初始化,推导的类型是 std::intializer_list 的一个实例。但是如果相同的初始化递给相同的模板,类型推导会失败,代码不能编译
template<class T>
void TemplateFun(T param);
TemplateFun({1,2,3,4}); // 没办法推导T的类型
如果你明确模板的param的类型是一个不知道T类型的 std::initializer_list
template<class T>
void TemplateFun(std::initializer_list<T> initList);
TemplateFun({ 11, 23, 9 }); // T被推导成int,initList的类型是std::initializer_list<int>
所以 auto 和模板类型推导的本质区别就是 auto 假设大括号初始化代表的是std::initializer_list,但是模板类型推导却不是
C++14允许auto表示推导的函数返回值,而且C++14的lambda可能会在参数声明里面使用auto。但是,这里面的使用是复用了模板的类型推导,而不是 auto 的类型推导。所以一个使用 auto 声明的返回值的函数或者auto用在参数类型声明,返回一个大括号初始化或者以大括号作为参数就无法编译
auto createInitList()
{
return { 1, 2, 3 }; // 编译错误:不能推导出{ 1, 2, 3 }的类型
}
auto SetFun = [](const auto& newVal){...};
SetFun({1,2,3}); // 编译错误,不能推导出{ 1, 2, 3 }的类型
auto 类型推导通常和模板类型推导类似,但是auto类型推导假定大括号初始化代表的类型是std::initializer_list ,但是模板类型推导却不是这样
auto 在函数返回值或者lambda参数里面执行模板的类型推导,而不是通常意义的auto类型推导