c++ - raw - typeid(“”)!=typeid(const char*)
typeid c++ (3)
Estoy creando una biblioteca de C ++ que se basa en gran medida en RTTI (puente personalizable a otro idioma) y está muy confundida con el tipo de cadena literal.
Esta es una prueba simple que hice para mostrar el problema:
std::cout << typeid(const char*).name() << std::endl; // PKc
std::cout << std::any("").type().name() << std::endl; // PKc
std::cout << typeid("").name() << std::endl; // A1_c
Para mí, parece que los dos primeros imprimen el tipo de
const char*
, pero el último es una matriz.
¿Por qué los resultados para
std::any("").type()
y
typeid("")
diferentes?
¿Hay alguna forma de obtener el primer comportamiento, es decir, hacer que los resultados de los literales de cadena sean consistentes (uso la identificación de tipos para llamar a los diferentes manejadores de tipos)?
PS: las pruebas se realizan utilizando la versión 8.0.0-3 de Clang (tags / RELEASE_800 / final) en Ubuntu 19.04.
¿Por qué los resultados para
std::any("").type()
ytypeid("")
diferentes?
Acreditando a la siguiente reference :
template< class ValueType > any( ValueType&& value );
4) Construye un objeto con contenido inicial un objeto de tipo
std::decay_t<ValueType>
, inicializado directamente desdestd::forward<ValueType>(value)
.
std::decay_t<const char[1]>
es
const char*
.
Aquí hay una cita de FrankHB1989 en el
foro isocpp.org
, que creo que es relevante para entender
std::any
, en el contexto de esta pregunta:
[
std::any
] ni siquiera es para "cualquier objeto". Como he argumentado anteriormente, espero que la palabra "cualquiera" sea corta para "cualquier tipo de objeto de primera clase" (es decir, tipo de objeto no matriculado no cv), perostd::any
tiene un refinamiento adicional de CopyConstructible en el valor type, por lo que en realidad es para "cualquier tipo de objeto no matricial no cualificado cv copiable".
Como tal
¿Hay alguna forma de obtener el primer comportamiento, es decir, hacer que los resultados de los literales de cadena sean consistentes (uso la identificación de tipos para llamar a los diferentes manejadores de tipos)?
No hay forma de tener
std::any
de array (puede tener
std::any
de
std::array
, pero el literal de cadena no es un
std::array
), y no hay forma de hacer un
typeid("")
ser un puntero
Sin embargo, puede usar
std::decay_t<decltype("")>
para obtener el mismo tipo que el almacenado en
std::any
.
Como han mencionado otros, el tipo del literal de cadena
""
es
const char[1]
, como se explica, por ejemplo,
¿Cuál es el tipo de datos del literal de cadena en C ++?
.
El tipo almacenado en
std::any("")
es
const char*
porque está utilizando el siguiente constructor (
http://www.eel.is/c++draft/any.cons#8
):
// Effects: Constructs an object of type any that contains an object of
// type std::decay_t<T> direct-initialized with std::forward<T>(value).
template< class T>
any( T&& value );
En este caso,
T
es
const char(&)[1]
(el tipo del literal de cadena
""
), y por lo tanto
std::decay_t<const char(&)[1]>
le dará
const char*
, que es por qué el
typeid()
de
std::any("").type()
es el ID de tipo de
const char*
.
Es un error común que un literal de cadena tenga el tipo
const char*
.
No lo hace
Tiene el tipo
const char[<size + 1>]
(más uno para el terminador nulo).
por ejemplo,
""
tiene el tipo
const char[1]
.
Pero a menudo asignamos un literal de cadena a un
const char*
,
const char*
fuera de convención (y también porque de lo contrario activamos reglas especiales que resultan en
copiar
la cadena).
Además, las reglas de decaimiento del nombre de la matriz hacen que sea bastante difícil observar la matriz de un nombre en C (y, por extensión, C ++);
que
std::any
funciona de la manera que lo hace es un ejemplo de eso.