sintaxis - Eliminando el espacio de nombres del nombre de tipo en C++
sintaxis de c++ (5)
En C ++, cuando usamos typeid
para obtener el nombre de tipo de un objeto o clase, mostrará una cadena decorada (cortada). Yo uso cxxabi
para desenredarlo:
#include <cxxabi.h>
#include <typeinfo>
namespace MyNamespace {
class MyBaseClass
{
public:
const std::string name()
{
int status;
char *realname = abi::__cxa_demangle(typeid (*this).name(),0,0, &status);
std::string n = realname;
free(realname);
return n;
}
};
}
int main()
{
MyNamespace::MyBaseClass h;
std::cout << h.name() << std::endl;
}
La salida en gcc
es:
MyNamespace :: MyBaseClass
Necesito eliminar MyNamespace::
de la cadena anterior. Puedo eliminarlos manipulando cadenas .
Pero, ¿existe una forma estándar con cxxabi
u otras bibliotecas para hacer esto o una solución clara? (Al menos portátil entre gcc y Visual C ++)
Investigué cxxabi y otras bibliotecas de c ++ para este problema y no hay ningún método predefinido para eliminar los espacios de nombres de eso (al menos en Google).
Me pregunto por qué no quieres manipular la cadena?
La mejor solución y totalmente portátil (probada en gcc y vc ++) se encuentra a continuación:
return n;
return n.substr(n.find_last_of('':'')+1);
Cuando busca n
en dos puntos de last (= lastColorPos
) y captura la cadena de lastColorPos
para finalizar, definitivamente es el nombre de la clase.
No hay una manera estándar de hacer esto, punto, porque no hay una manera estándar de hacer el nombre del hombre. Cómo representar nombres fue intencionalmente no especificado. No hay ABI en el estándar de C ++. La función que está utilizando, abi::__cxa_demangle
, es parte de Itanium C ++ ABI. Esa función puede o no existir en otro lugar.
En cuanto a la forma de hacer lo que desea con el Itanium C ++ ABI, no proporcionan tal capacidad intencionalmente.
No sé si esto correspondería a sus necesidades, pero me gustó mencionarlo.
Hay algo que puedes hacer para obtener el nombre de una clase que escribiste. Y puede ser considerado como portátil entre gcc y Visual C ++.
En GCC hay una variable mágica llamada __ FUNCIÓN __ como parte de las extensiones de lenguaje gnu c , que se tratan como una variable , en C ++. (El tratamiento difiere en C según la versión de GCC).
En Visual Studio hay una macro predefinida que tiene el mismo nombre y hace el mismo trabajo. La descripción está here .
Utiliza __ FUNCIÓN __ para obtener el nombre de la función actual. Entonces, para obtener el nombre de la clase, puede ser que puedas usarlo en el constructor de clases como este:
namespace MyNamespace
{
class MyBaseClass
{
public:
MyBaseClass(): myName(__FUNCTION__){}
string name() { return myName; }
private:
string myName;
};
}
Entonces, obtendrás la respuesta "MyBaseClass"
si llamas a la función name()
de una instancia de esta clase.
Si solo desea definir una función miembro que devolverá el nombre de cadena de la clase, sin el espacio de nombres, entonces me pregunto por qué usaría cxxabi
o incluso __FUNCTION__
o cualquier otra cosa, aparte de simplemente hacer esto:
namespace MyNamespace
{
class MyBaseClass
{
public:
//make the function const as well
std::string name() const { return "MyBaseClass"; }
};
}
Quiero decir que tienes control total sobre la implementación de la clase, entonces ¿por qué complicarte cuando una sola declaración de retorno es suficiente? También puede agregar otra función miembro:
std::string fullname() const { return "MyNamespace::MyBaseClass"; }
Echa un vistazo a este tema un tanto relacionado, tal vez obtendrás más sugerencias:
std::string removeNS( const std::string & source, const std::string & namespace_ )
{
std::string dst = source;
size_t position = source.find( namespace_ );
while ( position != std::string::npos )
{
dst.erase( position, namespace_.length() );
position = dst.find( namespace_, position + 1 );
}
return dst;
}
int main()
{
MyNamespace::MyBaseClass h;
std::cout << removeNS( h.name(), "MyNamespace::" ) << std::endl;
}