¿Por qué auto x{3} deduce una lista de inicializadores?
Me encanta auto
en C++11. Es maravilloso. Pero tiene una inconsistencia que realmente me pone de los nervios, porque tropiezo con ella todo el tiempo:
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>?!
Este extraño comportamiento es confuso para los recién llegados, y molesto para los usuarios experimentados C C++ tiene suficientes pequeñas inconsistencias y casos de esquina que uno tiene que tener en cuenta como está. ¿Puede alguien explicar por qué el comité de normas decidió introducir uno nuevo en este caso?
Podría entenderlo si declarara una variable de type std::initializer_list
era algo que era útil o se hacía con frecuencia, pero en mi experiencia casi nunca es deliberado -- y en los raros casos en los que querías hacerlo, cualquiera de
std::initializer_list<int> l{3};
auto l = std::initializer_list<int>{3};
auto l = {3}; // No need to specify the type
Funcionaría muy bien. Entonces, ¿cuál es la razón detrás del caso especial para auto x{i}
?
1 answers
Para hacer una larga historia corta:
- una expresión inicializadora entre corchetes
{}
no tiene ningún tipo por sí misma -
auto
tiene que inferir información de tipo -
int{3}
obviamente significa "crear un varint
con valor tomado de la lista inicializadora", por lo que su tipo es simplementeint
y se puede usar en cualquier contexto más amplio (int i = int{3}
funcionará yauto i = int{3}
puede deducir tipo, porque el lado derecho es obviamente de tipoint
) -
{3}
por sí mismo no tiene tipo ( no puede serint
, porque no es un valor sino una lista inicializadora ), por lo queauto
no funcionaría, pero, debido a que el comité consideró queauto
debería seguir funcionando en este caso, decidieron que el tipo "mejor" para la lista inicializadora (sí, sin tipo por definición) lo sería...std::initializer_list
, como probablemente ya adivinaste.
Pero, como usted señaló, esto hizo que todo el comportamiento de auto
bastante semánticamente inconsistente. Es por eso que hubo propuestas para cambiarlo - a saber N3681, N3912 y N3922 - presentados al comité. La propuesta anterior fue RECHAZADA como FI3 debido a que no hubo consenso del comité sobre este asunto, http://isocpp.org/files/papers/n3852.html#FI3 , current ( N3922 ) got adoptado ca. Q1 de 2015;
tl; dr puede suponer que compiladores compatibles con los estándares1 con compatibilidad con C++ de vanguardia2 o tienen la nueva semántica más sana ya está en su lugar, o lo tendrá en breve.
El Comité de Estandarización reconoció el problema al adoptar N3922 en el borrador de C++17.
- así que es
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
Ahora, para bien o para mal.
más leyendo:
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) aparentemente usa N3922 incluso en el modo C++11/C++14
2Clang 3.8, con la advertencia
Este es un cambio incompatible hacia atrás que se aplica a todas las versiones de lenguaje que permiten la deducción de tipos de auto (por solicitud del comité de C++).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:46:57