auto型别推导

auto型别推导

auto型别推导就是模板型别推导。在模板型别推导和 auto型别推导之间可以建立起一一映射,它们之间也确实存在双向的算法变换。

以 rx 为例:

int x = 27;
const auto& rx = x;  // x -> expr,auto -> T,const auto& -> ParamType

上述 auto 表达式可以等效为下面的模板型别推导:

template<typename T>
void func_for_rx(const T& param);

func_for_rx(x);

若要推导 auto 表达式(const auto& rx = x),编译器的行为就仿佛对应声明生成了一个函数模板和一个一次使用对应的初始化表达式针对该函数模板的调用。

关于数组退化指针和函数退化成函数指针,也和函数模板型别推导一致。

但有一个例外情况:大括号初始化表达式的处理方式,是 auto 型别表达式和模板型别推导的唯一不同之处。

auto 会假定用大括号括起的初始化表达式代表一个 std::initializer_list,但模板型别推导不会!

此时,auto 型别表达式和模板型别推导之间的映射关系不成立

// auto 型别推导
auto x = {11, 23, 9};   // auto 型别推导得到:x的型别是 std::initializer_list<int>


// 模板型别推导
template<typename T>
void func(T param);

f({11, 23, 9});         // 错误!无法推导出 T 的型别

        当采用声明的变量使用大括号初始化表达式进行初始化时,推导得到的型别是 std::initializer_list 的一个实例型别;但是如果向对应的函数模板传入一个同样的初始化表达式,类型推导就会失败,代码将不会通过编译。

// 除非在模板型别推导中指定 param 的型别是 std::initializer_list<T>
template<typename T> 
void func(initializer_list<int> param); 

f({11, 23, 9}); // 此时可以推导出 T 的型别

 

特别在 C++ 14 中,在函数返回值或 lamda 表达式的形参中使用 auto,意思是使用模板型别推导而非 auto 型别推导

  • 所以带有 auto 返回值的函数若要返回一个大括号括起的初始化表达式,是通不过编译的;
  • 同样的,用 auto 来指定中 lamda 式的形参型别时,也不能使用大括号括起的初始化表达式;
auto createInitList()     // 编译失败
{
    return {1, 2, 3};     // 无法为完成类型推导
}



std::vector<int> v;
...
auto resetV = [&v](const auto& newValue) { v = newValue; }   // 编译失败
...
resetV({1, 2, 3});

 

posted @ 2022-10-03 10:09  皮卡啰  阅读(67)  评论(0)    收藏  举报