Why does auto x {3} list initializer_list?

I like auto in C ++ 11. This is great. But he has one inconsistency that is really nervous because I travel all the time through it:

 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 behavior is confusing for beginners and annoying experienced users - C ++ has quite a few inconsistencies and corner cases that need to be kept in mind as it is. Can someone explain why the standardization committee decided to introduce a new one in this case?

I could understand this if declaring a variable like std::initializer_list was something useful or often executed, but in my experience it was almost never intentional - and in those rare cases when you really wanted to do this, any of

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

will work fine. So what is the reason for the special case for auto x{i} ?

+46
c ++ c ++ 11 initializer-list auto type-deduction
Sep 01 '14 at 19:57
source share
1 answer

In short:

  • a compressed initializer expression {} not a type in itself
  • auto should print type information
  • int{3} obviously means "create a var int with a value taken from the list of initializers", so 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 infer the type, because the right side is obviously of type int )
  • {3} by itself is not of type (it cannot be int because it is not a value, but a list of initializers), therefore auto will not work, because the committee believed that auto should still work in this case, they decided that the "best" type for the "initializer" list (yes, pointless by definition) would be ... std::initializer_list , as you probably already guessed.

But, as you pointed out, this made the whole auto behavior completely semantically inconsistent. That is why there were proposals for its change - namely, N3681 , N3912 and N3922 - submitted to the committee. The previous proposal was DENIED as FI3 due to the lack of consensus of the committee on this issue, http://isocpp.org/files/papers/n3852.html#FI3 , current ( N3922 ) received ca. Q1 2015 ;

tl; dr, you can assume that compilers 1 compatible with the C ++ version with C ++ 2 support either already have new, more reasonable semantics, or will have it in the near future.

The standardization committee recognized this problem by adopting N3922 in the C ++ 17 project.

- therefore he

 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:

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

2 Clang 3.8, with reservation

This is a backward-incompatible change that applies to all language versions that let you type out automatically (at the request of the C ++ committee).

+33
01 Sep '14 at 20:27
source share



All Articles