Ответ 1
Короче говоря:
- сжатое выражение инициализатора
{}
не имеет типа само по себе -
auto
должен выводить информацию о типе -
int{3}
, очевидно, означает "создать varint
со значением, взятым из списка инициализаторов", поэтому его тип простоint
и может использоваться в любом более широком контексте (int i = int{3}
будет работать, аauto i = int{3}
может выведите тип, потому что правая сторона, очевидно, имеет типint
) -
{3}
сам по себе не имеет типа (он не может бытьint
, потому что это не значение, а список инициализаторов), поэтомуauto
не будет работать, потому что комитет считал, чтоauto
должен по-прежнему работать в этом случае, они решили, что "лучший" тип для списка "инициализатор" (да, беспредметный по определению) будет...std::initializer_list
, как вы уже, наверное, догадались.
Но, как вы указали, это сделало целое поведение auto
вполне семантически непоследовательным. Вот почему были предложения по его изменению - а именно N3681, N3912 и N3922 - представлены в комитет. Предыдущее предложение было ОТКАЗЫНО как FI3 из-за отсутствия консенсуса комитета по этому вопросу, http://isocpp.org/files/papers/n3852.html#FI3, current (N3922) получил принят ca. Q1 2015 года;
tl; dr вы можете предположить, что совместимые со стандартом компиляторы 1 с версия C + + с поддержкой С++ 2 либо уже имеет новую, более разумную семантику, либо будет иметь ее в ближайшее время.
Комитет по стандартизации признал эту проблему, приняв N3922 в проект С++ 17.
- поэтому он
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/
1 GCC 5.1 (& up) по-видимому, использует N3922 даже в режиме С++ 11/С++ 14
2 Clang 3.8, с оговоркой
Это обратное-несовместимое изменение, которое применяется ко всем языковым версиям, которые позволяют выводить тип автоматически (по запросу комитета С++).