Почему auto x {3} выводит initializer_list?
4520 просмотра
1 ответ
Я люблю auto
в C ++ 11. Это замечательно. Но у него есть одно несоответствие, которое действительно действует мне на нервы, потому что я постоянно спотыкаюсь об этом:
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 ++ достаточно мало несоответствий и угловых случаев, о которых нужно помнить как есть. Кто-нибудь может объяснить, почему комитет по стандартам решил ввести новый в этом случае?
Я мог бы понять это, если объявление переменной типа std::initializer_list
было чем-то полезным или делалось часто, но по моему опыту это почти никогда не было преднамеренным - и в тех редких случаях, когда вы хотели это сделать, любой из
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 плюса
Короче говоря:
- выражение инициализатора в скобках
{}
само по себе не имеет типа auto
должен выводить информацию о типеint{3}
очевидно означает «создатьint
переменную со значением, взятым из списка инициализаторов», таким образом, ее тип является справедливым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 , текущий ( N3922 ) был принят ок. 1 квартал 2015 года ;
Т.Л., д - р можно считать , что соответствующие стандартам компиляторы 1 с передним краем C ++ поддержка 2 либо иметь новые, более здравомыслящие иш семантики уже на месте, или будет иметь его в ближайшее время .
Комитет по стандартизации признал проблему, приняв N3922 в проект C ++ 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 (и выше), очевидно, использует N3922 даже в режиме C ++ 11 / C ++ 14
2 лязга 3.8, с оговоркой
Автор: vaxquis Размещён: 01.09.2014 08:27Это обратно несовместимое изменение, которое применяется ко всем языковым версиям, которые позволяют вычитать тип из auto (согласно запросу комитета C ++).
Вопросы из категории :
- c++ What are the barriers to understanding pointers and what can be done to overcome them?
- c++ Какой самый простой способ для анализа файла INI в C ++?
- c++ Когда вы должны использовать «друг» в C ++?
- c++ Как вы очищаете переменную stringstream?
- c++11 Можно ли напечатать тип переменной в стандартном C ++?
- c++11 Проверьте, имеет ли класс функцию-член с заданной сигнатурой
- c++11 Что такое умный указатель и когда я должен его использовать?
- c++11 Как вы можете перебирать элементы std :: tuple?
- auto Сколько это слишком много с ключевым словом auto C ++ 11?
- auto C ++ авто ключевое слово. Почему это волшебство?
- auto Какой тип лямбда-выражения при выводе с помощью «auto» в C ++ 11?
- auto Does 'auto' type assignments of a pointer in c++11 require '*'?
- initializer-list Ошибка компиляции C: «Объект переменного размера не может быть инициализирован»
- initializer-list initializer_list и переместить семантику
- initializer-list Когда использовать инициализатор в скобках?
- initializer-list Тернарный оператор + конструктор C ++ 11 из initializer_list
- type-deduction Почему auto x {3} выводит initializer_list?
- type-deduction Понимание вывода типа через std :: is_same
- type-deduction Обнаружение типов в TypeScript
- type-deduction Вывод примитивного типа из необработанной памяти и анализаторов классов