decltype en la variable de tipo de referencia con llaves
Considere el siguiente código :
#include <type_traits>
int main() {
const int& p = 42;
auto v1 = decltype(p){};
static_assert(std::is_same_v<decltype(v1), int>);
decltype(p) v2{};
static_assert(std::is_same_v<decltype(v2), const int&>);
// auto v3 = X(const int&)X {};
}
El tipo de v1
se deduce como int
. Al mismo tiempo, v2
se espera que el tipo de const int&
. Creo que el primer paso para v1
podría tratarse como agregar un alias de tipo más using T = decltype(p);
y luego auto v4 = T{};
. ¿Cómo trata el compilador esta expresión ( decltype(p){}
o T{}
)? Sé que esa {}
parte es para la creación de instancias, pero ¿cómo el tipo resultante de v1
no es un tipo de referencia?
Otra pregunta más: ¿hay alguna manera de declarar una v3
variable del mismo tipo que si se v1
usa un tipo anotado explícitamente const int&
(en lugar de decltype(p)
)?
Se agradecería cualquier enlace al estándar.
Respuestas
(Para los votantes en contra: si votó en contra porque cree que citar a Scott Meyers no es equivalente a citar el estándar, bueno ...)
Como puede leer de Effective Modern C ++ (aumentado con la parte de la errata a la que puede llegar buscando Case 2:
en ese enlace, y eso solo hace que la siguiente lectura sea más simple, pero no es esencial para la pregunta):
Si no
ParamType
es una referencia [...] siexpr
el tipo es una referencia, ignore la parte de referencia. Si [...]expr
esconst
, Ingore eso también. Si es asívolatile
, ignóralo también.
donde param
es el especificador de declaración, que en su caso es solo auto
, es decir, una no referencia.
En otras palabras, está creando a v1
través de simple auto
(no auto&
), es decir, por copia, por lo que no importa si lo está inicializando con una entidad que es referencia o no, o incluso con const
o no ( volatile
o no, fwiw), porque lo estás copiando.
Piense en el caso más simple,
int i = 3;
int& p = i;
auto v1 = p;
en lo que v1
respecta, realmente no es importante si se inicializa con uno ( i
) u otro ( p
) nombre por el que se conoce la misma entidad, porque obtendrá una copia de cualquier valor que tenga esa entidad.
auto
la deducción de tipo funciona igual que la deducción de tipo de plantilla (excepto por una diferencia en cómo tratan con el inicializador arriostrado, que no es relevante en este caso), y para ambos puede consultar el C ++ efectivo moderno de Scott Meyers .