c++ - ¿Cuál es el resultado de decltype("Hola")?
c++11 string-literals (1)
Obtengo resultados inesperados de todos los compiladores en los que intenté lo siguiente (GCC 4.7.2, GCC 4.8.0 beta, ICC 13.0.1, Clang 3.2, VC10):
#include <type_traits>
int main()
{
// This will fire
static_assert(
std::is_same<decltype("Hello"), char const[6]>::value,
"Error!"
);
}
Hubiera esperado que la afirmación en tiempo de compilación anterior no se activara, pero lo hace. Después de todo, este no (como se esperaba):
#include <type_traits>
int main()
{
char const hello[6] = "Hello";
// This will not fire
static_assert(
std::is_same<decltype(hello), char const[6]>::value,
"Error!"
);
}
Entonces, ¿cuál es el resultado de decltype("Hello")
acuerdo con el estándar C ++ 11 (las referencias son muy apreciadas)? ¿Con qué debería compararlo para que no se active la afirmación en tiempo de compilación anterior?
[ Nota: Originalmente, esto no tenía la intención de ser una pregunta auto-respondida; Solo encontré la respuesta yo mismo mientras describía mis intentos de investigar, y pensé que habría sido agradable compartirla. ]
De acuerdo con el Anexo C (2.14.5) de la Norma C ++ 11:
El tipo de un literal de cadena se cambia de "array of char" a " array of const char ". [....]
Además, el Párrafo 7.1.6.2/4 especifica (sobre el resultado de decltype
):
El tipo indicado por
decltype(e)
se define de la siguiente manera:- si
e
es una expresión de id no aparente o un acceso de miembro de clase no apareado (5.2.5),decltype(e)
es el tipo de la entidad nombrada pore
. Si no existe tal entidad, o sie
nombra un conjunto de funciones sobrecargadas, el programa está mal formado;- de lo contrario, si
e
es un valordecltype(e)
,decltype(e)
esT&&
, dondeT
es el tipo dee
;- de lo contrario, si
e
es un valordecltype(e)
,decltype(e)
esT&
, dondeT
es el tipo dee
;- De lo contrario,
decltype(e)
es el tipo dee
.
Como los literales de cadena son lvalues , de acuerdo con el párrafo anterior y el párrafo del anexo C, el resultado de decltype("Hello")
es una referencia lvalue a una matriz de tamaño 6 de caracteres estrechos constantes:
#include <type_traits>
int main()
{
// This will NOT fire
static_assert(
std::is_same<decltype("Hello"), char const (&)[6]>::value,
"Error!"
);
}
Finalmente, aunque la variable hello
también es un lvalue, la segunda aserción en tiempo de compilación del texto de la pregunta no se activa , porque hello
es una expresión id no aparente , lo que hace que caiga en el primer elemento de la lista anterior del Párrafo 7.1 .6.2 / 4. Por lo tanto, el resultado de decltype(hello)
es el tipo de entidad llamada por hello
, que es char const[6]
.