raw c++ c++17 rtti string-literals

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() y typeid("") 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 desde std::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), pero std::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.