Pregunta ¿Hay una macro __CLASS__ en C ++?


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


75
2017-11-03 11:42


origen


Respuestas:


Lo más cercano que hay es llamar typeid(your_class).name() - pero esto produce el nombre destrozado específico del compilador.

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


53
2017-11-03 11:44



El problema con el uso typeid(*this).name() es que no hay this puntero en una llamada al 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 <class>::<method>(), recortando el tipo de retorno, modificadores y argumentos de qué __PRETTY_FUNCTION__ te dio.

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__)

56
2018-04-02 22:24



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


9
2017-11-03 11:46



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

Ejemplo

#include <boost/type_index.hpp>

class foo_bar
{
    int whatever;
};

namespace bti =  boost::typeindex;

template <typename T>
void from_type(T t)
{
    std::cout << "\tT = " << bti::type_id_with_cvr<T>().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<decltype(fb)>().pretty_name() << "\n";
}

Compilado 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


8
2017-08-27 13:27



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


4
2018-04-29 03:37



Si tu compilador es g++ y estas pidiendo __CLASS__ porque quiere una forma de obtener el nombre del método actual, incluida la clase, __PRETTY_FUNCTION__ debería ayudar (según info gcc, sección 5.43 nombres de funciones como cadenas)


3
2017-11-03 11:52



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


2
2017-11-03 11:48



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) + "()";
}

1
2018-05-14 03:19



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.


1
2017-11-14 09:21



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

template <class T>
class ClassName
{
public:
  static std::string Get()
  {
    // Get function name, which is "ClassName<class T>::Get"
    // The template parameter 'T' is the class name we're looking for
    std::string name = __FUNCTION__;
    // Remove "ClassName<class " ("<class " is 7 characters long)
    size_t pos = name.find_first_of('<');
    if (pos != std::string::npos)
      name = name.substr(pos + 7);
    // Remove ">::Get"
    pos = name.find_last_of('>');
    if (pos != std::string::npos)
      name = name.substr(0, pos);
    return name;
  }
};

template <class T>
std::string GetClassName(const T* _this = NULL)
{
  return ClassName<T>::Get();
}

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

template <class T>
class Logger
{
public:
  void Log(int value)
  {
    std::cout << GetClassName<T>()  << ": " << value << std::endl;
    std::cout << GetClassName(this) << ": " << value << std::endl;
  }
};

class Example : protected Logger<Example>
{
public:
  void Run()
  {
    Log(0);
  }
}

El resultado de Example::Run entonces será

Example: 0
Logger<Example>: 0

1
2018-01-22 12:29



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

#define __CLASS__ std::remove_reference<decltype(classMacroImpl(this))>::type

template<class T> 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


1
2018-04-27 17:01