传统上,人们从左到右阅读变量声明/定义,例如:
std::vector<float> arr = {3.14, 1.414, 2.71, -0.2};
所以
{3.14, 1.414, 2.71, -0.2}
的含义就很清楚了:我们有一个std::vector<float>
类型变量arr
,我们想用四个元素来初始化它:3.14、1.414、2.71、-0.2
但是
auto
的引入让这变得更加晦涩难懂。下面的 auto
关键字有什么作用?:
auto arr = {3.14, 1.414, 2.71, -0.2};
我的 clangd 提示这里的 arr 是:
std::initializer_list<double>
,这是所有标准兼容编译器中唯一的类型推导结果还是某些编译器可以在这里自由地将 auto arr 设为 std::vector<double>
?
一个更详细和复杂的示例:,我有一个模板函数,可以从正好三个
std::vector
中获取最大值:
template <typename T>
constexpr T getMax(const std::vector<T> &v1, const std::vector<T> &v2, const std::vector<T> &v3)
{
auto arr = { std::views::all(v1), std::views::all(v2), std::views::all(v3)};
auto view = std::views::join(arr);
return std::ranges::max(view);
}
在此代码片段中,我们定义了一个
auto arr
变量:
auto arr = { std::views::all(v1), std::views::all(v2), std::views::all(v3)};
它从 gcc 推导的类型是:
std::initializer_list<std::ranges::ref_view<std::vector<std::string_view>>>
,什么要求编译器必须将 auto
类型推导为这个冗长的具体类型?这个结果是唯一的还是每个编译器只要遵循一些规则就可以自由地进行自己的推论?
它应该始终是
std::initializer_list
。
如果初始化是复制列表初始化,则声明 std::initializer_list 应先于 ([basic.lookup.general]) 占位符类型说明符。
[示例1:
auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int> auto x2 = { 1, 2.0 }; // error: cannot deduce element type auto x3{ 1, 2 }; // error: not a single element auto x4 = { 3 }; // decltype(x4) is std::initializer_list<int> auto x5{ 3 }; // decltype(x5) is int
—结束示例]