为什么auto x {3}推导出initializer_list? [英] Why does auto x{3} deduce an initializer_list?

查看:160
本文介绍了为什么auto x {3}推导出initializer_list?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我喜欢C ++ 11中的 auto 。这是美好的。但它有一个不一致,真的在我的神经,因为我一直在它的所有时间:

  int i = 3; // i是一个值为3的整型
int i = int {3}; // i是一个值为3的int
int i(3); // i是一个值为3的整数(可能变窄,不是这种情况)
int i {3}; // i是一个值为3的整型

auto i = 3; // i是一个值为3的int
auto i = int {3}; // i是一个值为3的int
auto i(3); // i是一个值为3的int
auto i {3}; // wtf,i是std :: initializer_list< int>?!

这个奇怪的行为令新用户感到困惑,并且让有经验的用户烦恼 - C ++有足够的不一致性一个人必须记住的角色案件,因为它是。任何人都可以解释为什么标准委员会决定在这种情况下引入一个新的?



如果声明一个变量 std :: initializer_list 是有用的或频繁做的东西,但在我的经验中,它几乎从来不是故意的 - 在很少的情况下,你确实想做,任何

  std :: initializer_list< int> 1 {3}; 
auto l = std :: initializer_list< int> {3};
auto l = {3}; //不需要指定类型

就可以正常工作。那么 auto x {i}

解决方案

长篇小说:




  • 一个大括号的初始化表达式 {} 没有类型本身

  • 自动必须推断类型信息

  • int {3} 显然意味着创建一个 int var取值从初始化列表,因此它的类型只是 int 并且可以在任何更广泛的上下文中使用( int i = int {3} 将工作, auto i = int {3} 可以推导类型,因为右侧显然是类型 int

  • code> {3} 本身没有类型(不能 int 不是,而是初始值列表),因此 auto code> auto 在这种情况下仍然应该工作,他们决定最好的类型(是的,定义的typeless)初始化列表将是... std



但是,正如你所指出的,这使得整个行为 auto 很语义上不一致。这就是为什么有改变的建议,即 N3681 N3912 N3922 提交给委员会。之前的提案被拒绝为FI3,因为没有关于此事的委员会一致同意, http:// isocpp。 org / files / papers / n3852.html#FI3 ,当前( N3922 )获得了 采用 ca. 2015年第Q1期;



tl; dr 您可以假设符合标准的编译器 1 llvm.org/cxx_status.html#n3922rel =nofollow>出血的C ++支持 2 有新的,更多的sane-ish语义已经到位,或将有它很快。


标准化委员会通过将N3922纳入草案C ++ 17来承认这个问题。


- 所以它是

  auto x1 = {1,2} // decltype(x1)is std :: initializer_list< int> 
auto x2 = {1,2.0}; //错误:无法推导元素类型
auto x3 {1,2}; //错误:不是单个元素
auto x4 = {3}; // decltype(x4)is std :: initializer_list< int>
auto x5 {3}; // decltype(x5)is int


$ b /jtc1/sc22/wg21/docs/papers/2013/n3681.htmlrel =nofollow> 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/






1 GCC 5.1(& up)显然使用N3922 even


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



I love auto in C++11. It's wonderful. But it has one inconsistency that really gets on my nerves, because I trip over it all the time:

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>?!

This strange behaviour is confusing for newcomers, and annoying for experienced users -- C++ has enough little inconsistencies and corner cases that one has to keep in mind as it is. Can anybody explain why standards committee decided to introduce a new one in this case?

I could understand it if declaring a variable of type std::initializer_list was something that was useful or done frequently, but in my experience it's almost never deliberate -- and in the rare cases where you did want to do it, any of

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

would work just fine. So what's the reason behind the special case for auto x{i}?

解决方案

To make long story short:

  • a braced initializer expression {} has no type by itself
  • auto has to infer type information
  • int{3} obviously means "create an int var with value taken from initializer list", thus its type is just int and can be used in any wider context (int i = int{3} will work and auto i = int{3} can deduce type, because right side is obviously of type int)
  • {3} by itself has no type (it can't be int, because it's not a value but an initializer list), so auto wouldn't work — but, because committee considered that auto should still work in this case, they decided that the "best" type for (yeah, typeless by definition) initializer list would be... std::initializer_list, as you already probably guessed.

But, as you pointed out, this made the whole behaviour of auto quite semantically inconsistent. That's why there were proposals to change it — namely N3681, N3912 and N3922 — submitted to the committee. Former proposal was REJECTED as FI3 due to no committee consensus on this matter, http://isocpp.org/files/papers/n3852.html#FI3 , current (N3922) got adopted ca. Q1 of 2015;

tl;dr you may assume that standards-compliant compilers1 with bleeding-edge C++ support2 either have the new, more sane-ish semantics already in place, or will have it shortly.

The Standardization Committee acknowledged the problem by adopting N3922 into draft C++17.

— so it's

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

now, for better or worse.

further reading:

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) apparently uses N3922 even in C++11/C++14 mode

2Clang 3.8, with the caveat

This is a backwards-incompatible change that is applied to all language versions that allow type deduction from auto (per the request of the C++ committee).

这篇关于为什么auto x {3}推导出initializer_list?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆