为什么自动x {3}会推导出initializer_list?

我喜欢C ++ 11中的auto x{i}。 太好了 但是它确实有一种不协调感,因为我一直都在不停地跳下去:

int i = 3;       // i is an int with value 3
int i = int{3};  // i is an int with value 3
int i(3);        // i is an int with value 3 (possibly narrowing, not in this case)
int i{3};        // i is an int with value 3

auto i = 3;      // i is an int with value 3
auto i = int{3}; // i is an int with value 3
auto i(3);       // i is an int with value 3
auto i{3};       // wtf, i is a std::initializer_list<int>?!

这种奇怪的行为使新手感到困惑,也使经验丰富的用户感到烦恼-C ++几乎没有什么不一致性和极端情况,因此必须牢记。 谁能解释为什么标准委员会决定在这种情况下引入一个新的标准?

如果声明一个类型为auto x{i}的变量是有用的或经常执行的,则我可以理解,但是以我的经验,这几乎从来不是故意的-在极少数情况下,您确实想这样做

std::initializer_list<int> l{3};
auto l = std::initializer_list<int>{3};
auto l = {3}; // No need to specify the type

会很好。 那么auto x{i}特殊情况背后的原因是什么?

1个解决方案
41 votes

简而言之:

  • 支撑初始化表达式auto本身没有类型
  • auto必须推断类型信息
  • auto显然意味着“使用从初始化列表中获取的值创建int var”,因此其类型仅为auto,可以在任何更广泛的上下文中使用(auto可以使用,而std::initializer_list可以推断出类型,因为右侧显然是int
  • auto本身没有类型(不能为int,因为它不是值,而是初始化列表),因此auto无法正常工作-但由于委员会认为auto在这种情况下仍应正常工作,他们决定 初始化程序列表的“最佳”类型(是的,根据定义是无类型的)将是... std::initializer_list,您可能已经猜到了。

但是,正如您所指出的那样,这使auto的整个行为在语义上非常不一致。 这就是为什么向委员会提交了对其进行更改的提案(即N3681,N3912和N3922)的原因。 由于未就此事达成任何委员会共识,因此先前的提案被拒绝为FI3。 2015年第一季度;

tl;博士,您可能会假设具有尖端C ++支持2的符合标准的编译器1要么已经具有新的,更合理的语义,要么很快就会拥有它。

标准化委员会通过在C ++ 17草案中采用N3922来承认这一问题。

- 所以是

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

现在,无论好坏。

进一步阅读:

[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3681.html]

[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3912.html]

[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3922.html]

[http://scottmeyers.blogspot.com/2014/03/if-braced-initializers-have-no-type-why.html]

[http://herbsutter.com/2014/11/24/updates-to-my-trip-report/]


1GCC 5.1(&up)显然甚至在C ++ 11 / C ++ 14模式下也使用N3922

2 Clang 3.8,警告

这是一个向后不兼容的更改,适用于所有允许从auto进行类型推断的语言版本(根据C ++委员会的要求)。

vaxquis answered 2019-11-17T09:35:05Z
translate from https://stackoverflow.com:/questions/25612262/why-does-auto-x3-deduce-an-initializer-list