带auto的initializer_list包含多个表达式

Vik*_*nko 23 c++ language-lawyer auto c++17

相当简单的问题,

auto x11 {1,2,3,4};
auto x1 = {1,2,3,4};
auto x22 {1.0, 2.25, 3.5};
auto x2 = {1.0, 2.25, 3.5};
Run Code Online (Sandbox Code Playgroud)

据我了解,这里应该没有区别=.但是,使用llvm/clang 6.0.0(使用--std = c ++ 17),我得到:

main1.cpp:35:17: error: initializer for variable 'x11' with type 'auto' contains multiple
  expressions
auto x11 {1,2,3,4};
~~~~~~~~    ^

main1.cpp:37:20: error: initializer for variable 'x22' with type 'auto' contains multiple
  expressions
auto x22 {1.0, 2.25, 3.5};
Run Code Online (Sandbox Code Playgroud)

从Stroustroup的C++书籍,第162页:

auto x1 {1,2,3,4}; // x1 is an initializer_list<int>
auto x2 {1.0, 2.25, 3.5 }; // x2 is an initializer_list of<double>
Run Code Online (Sandbox Code Playgroud)

那么,在那里没有=真的有问题吗?

son*_*yao 22

自C++ 17以来,自动类型推导的规则发生了变化.

(自C++ 17开始)
在直接列表初始化中(但不在copy-list-initalization中),当从braced-init-list推导出auto的含义时,braced-init-list必须只包含一个元素,auto的类型将是该元素的类型:

auto x1 = {3}; // x1 is std::initializer_list<int>
auto x2{1, 2}; // error: not a single element
auto x3{3};    // x3 is int
               // (before C++17 x2 and x3 were both std::initializer_list<int>)
Run Code Online (Sandbox Code Playgroud)

所以在C++ 17之前,样本中的所有变量都可以正常工作并具有类型std::initializer_list<int>.但是从C++ 17开始,对于直接初始化(即for x11x22),braced-initializer必须只包含一个元素(并且它们的类型将是元素的类型),然后变成格式错误的代码.

有关更多信息,请参阅N3922N3681.

  • @Aconcagua:我认为原因是`autoviousInt {1};`毕竟不是一个`int`,这让许多人感到困惑/烦恼.具有"{...}"类型取决于表达式的数量可能会更加令人困惑 - 所以他们只是禁止它.可能没有*那么多代码使用统一初始化,并且修复很简单(更改为copy-list-initialization). (6认同)
  • 你知道这种标准变化背后的原因吗?它可能会破坏现有的代码,所以我想应该有一个好的... (2认同)