¿Hay una macro __CLASS__ en C ++?

¿Hay una macro __CLASS__ en C ++ que da el nombre de clase similar a la macro __FUNCTION__ que da el nombre de la función

Lo más parecido que hay es llamar a typeid(your_class).name() , pero esto produce un nombre destrozado específico del comstackdor.

Para usarlo dentro de la clase solo typeid(*this).name()

El problema con el uso de typeid(*this).name() es que no hay this puntero en una llamada de método estático. La macro __PRETTY_FUNCTION__ informa un nombre de clase en funciones estáticas así como en llamadas a métodos. Sin embargo, esto solo funcionará con gcc.

Aquí hay un ejemplo de extracción de información a través de una interfaz de estilo macro.

 inline std::string methodName(const std::string& prettyFunction) { size_t colons = prettyFunction.find("::"); size_t begin = prettyFunction.substr(0,colons).rfind(" ") + 1; size_t end = prettyFunction.rfind("(") - begin; return prettyFunction.substr(begin,end) + "()"; } #define __METHOD_NAME__ methodName(__PRETTY_FUNCTION__) 

La macro __METHOD_NAME__ devolverá una cadena de la forma ::() , recortando el tipo de devolución, modificadores y argumentos de lo que __PRETTY_FUNCTION__ le da.

Para algo que extrae solo el nombre de la clase, se debe tener cuidado para atrapar situaciones donde no hay clase:

 inline std::string className(const std::string& prettyFunction) { size_t colons = prettyFunction.find("::"); if (colons == std::string::npos) return "::"; size_t begin = prettyFunction.substr(0,colons).rfind(" ") + 1; size_t end = colons - begin; return prettyFunction.substr(begin,end); } #define __CLASS_NAME__ className(__PRETTY_FUNCTION__) 

Aún no. (Creo que __class__ se propone en alguna parte). También puede intentar extraer la parte de clase de __PRETTY_FUNCTION__ .

Me gustaría sugerir boost :: typeindex , que aprendí de “Effective Modern C ++” de Scott Meyer. Aquí hay un ejemplo básico:

Ejemplo

 #include  class foo_bar { int whatever; }; namespace bti = boost::typeindex; template  void from_type(T t) { std::cout << "\tT = " << bti::type_id_with_cvr().pretty_name() << "\n"; } int main() { std::cout << "If you want to print a template type, that's easy.\n"; from_type(1.0); std::cout << "To get it from an object instance, just use decltype:\n"; foo_bar fb; std::cout << "\tfb's type is : " << bti::type_id_with_cvr().pretty_name() << "\n"; } 

Comstackdo con "g ++ --std = c ++ 14" esto produce lo siguiente

Salida

Si desea imprimir un tipo de plantilla, eso es fácil.

T = doble

Para obtenerlo de una instancia de objeto, solo use decltype:

El tipo de fb es: foo_bar

Creo que usar __PRETTY_FUNCTION__ es lo suficientemente bueno, aunque también incluye espacio de nombres, es decir, namespace::classname::functionname hasta que __CLASS__ esté disponible.

Si tu comstackdor es g++ y estás pidiendo __CLASS__ porque quieres una manera de obtener el nombre del método actual incluyendo la clase, __PRETTY_FUNCTION__ debería ayudar (de acuerdo con info gcc , sección 5.43 Nombres de funciones como cadenas ).

Si está hablando MS C ++ (Debe indicar, esp, ya que __FUNCTION__ es una extensión no estándar), hay símbolos __FUNCDNAME__ y __FUNCSIG__ que puede analizar

Puede obtener el nombre de la función incluyendo el nombre de la clase. Esto puede procesar funcitones de tipo C.

 static std::string methodName(const std::string& prettyFunction) { size_t begin,end; end = prettyFunction.find("("); begin = prettyFunction.substr(0,end).rfind(" ") + 1; end -= begin; return prettyFunction.substr(begin,end) + "()"; } 

Mi solución:

 std::string getClassName(const char* fullFuncName) { std::string fullFuncNameStr(fullFuncName); size_t pos = fullFuncNameStr.find_last_of("::"); if (pos == std::string::npos) { return ""; } return fullFuncNameStr.substr(0, pos-1); } #define __CLASS__ getClassName(__FUNCTION__) 

Yo trabajo para Visual C ++ 12.

Aquí hay una solución basada en la macro __FUNCTION__ y las plantillas C ++:

 template  class ClassName { public: static std::string Get() { // Get function name, which is "ClassName::Get" // The template parameter 'T' is the class name we're looking for std::string name = __FUNCTION__; // Remove "ClassName::Get" pos = name.find_last_of('>'); if (pos != std::string::npos) name = name.substr(0, pos); return name; } }; template  std::string GetClassName(const T* _this = NULL) { return ClassName::Get(); } 

Aquí hay un ejemplo de cómo esto podría usarse para una clase de registrador

 template  class Logger { public: void Log(int value) { std::cout << GetClassName() << ": " << value << std::endl; std::cout << GetClassName(this) << ": " << value << std::endl; } }; class Example : protected Logger { public: void Run() { Log(0); } } 

La salida de Example::Run será entonces

 Example: 0 Logger: 0 

Si necesita algo que realmente produzca el nombre de la clase en tiempo de comstackción, puede usar C ++ 11 para hacer esto:

 #define __CLASS__ std::remove_reference::type template T& classMacroImpl(const T* t); 

Reconozco que esto no es lo mismo que __FUNCTION__ pero encontré esta publicación mientras buscaba una respuesta como esta. :RE

Esto funciona bastante bien si está dispuesto a pagar el costo de un puntero.

 class State { public: State( const char* const stateName ) :mStateName( stateName ) {}; const char* const GetName( void ) { return mStateName; } private: const char * const mStateName; }; class ClientStateConnected : public State { public: ClientStateConnected( void ) : State( __FUNCTION__ ) {}; }; 

Funciona con msvc y gcc también

 #ifdef _MSC_VER #define __class_func__ __FUNCTION__ #endif #ifdef __GNUG__ #include  #include  char *class_func(const char *c, const char *f) { int status; static char buff[100]; char *demangled = abi::__cxa_demangle(c, NULL, NULL, &status); snprintf(buff, sizeof(buff), "%s::%s", demangled, f); free(demangled); return buff; } #define __class_func__ class_func(typeid(*this).name(), __func__) #endif 

El siguiente método (basado en methodName () arriba) también puede manejar entradas como “int main (int argc, char ** argv)”:

 string getMethodName(const string& prettyFunction) { size_t end = prettyFunction.find("(") - 1; size_t begin = prettyFunction.substr(0, end).rfind(" ") + 1; return prettyFunction.substr(begin, end - begin + 1) + "()"; }