Frage Gibt es in C ++ ein Makro __CLASS__?


Gibt es ein __CLASS__ Makro in C ++, das den Klassennamen ähnlich gibt __FUNCTION__ Makro, das den Funktionsnamen angibt


75
2017-11-03 11:42


Ursprung


Antworten:


Das nächste, was es gibt, ist anzurufen typeid(your_class).name() - aber das erzeugt Compiler-spezifischen Mangled Name.

Um es nur innerhalb der Klasse zu verwenden typeid(*this).name()


53
2017-11-03 11:44



Das Problem mit der Verwendung typeid(*this).name() ist, dass es keine gibt this Zeiger in einem statischen Methodenaufruf. Das Makro __PRETTY_FUNCTION__ meldet einen Klassennamen sowohl in statischen Funktionen als auch in Methodenaufrufen. Dies funktioniert jedoch nur mit gcc.

Hier sehen Sie ein Beispiel für das Extrahieren der Informationen über eine Makroschnitt-Schnittstelle.

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

Das Makro __METHOD_NAME__ gibt eine Zeichenfolge des Formulars zurück <class>::<method>(), trimmen den Rückgabetyp, Modifikatoren und Argumente von was __PRETTY_FUNCTION__ gibt Ihnen.

Für etwas, das nur den Klassennamen extrahiert, müssen einige Situationen vermieden werden, in denen es keine Klasse gibt:

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



Noch nicht. (Ich denke __class__ wird irgendwo vorgeschlagen). Sie können auch versuchen, einen Klassenteil zu extrahieren __PRETTY_FUNCTION__.


9
2017-11-03 11:46



Ich möchte vorschlagen boost :: typeindex, von dem ich in Scott Meyers "Effective Modern C ++" erfahren habe. Hier ein einfaches Beispiel:

Beispiel

#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";
}

Zusammengestellt mit "g ++ --std = c ++ 14" ergibt dies folgendes

Ausgabe

Wenn Sie einen Vorlagentyp drucken möchten, ist das ganz einfach.

T = doppelt

Um es von einer Objektinstanz zu bekommen, benutzen Sie einfach declltype:

Der Typ von fb ist: foo_bar


8
2017-08-27 13:27



Ich denke mit __PRETTY_FUNCTION__ ist gut genug, obwohl es auch Namespace enthält, d.h. namespace::classname::functionname bis __CLASS__ ist verfügbar.


4
2018-04-29 03:37



Wenn dein Compiler zufällig ist g++ und du fragst nach __CLASS__ weil Sie eine Möglichkeit haben möchten, den aktuellen Methodennamen einschließlich der Klasse zu erhalten, __PRETTY_FUNCTION__ sollte helfen (nach info gcc, Sektion 5.43 Funktionsnamen als Strings).


3
2017-11-03 11:52



Wenn Sie MS C ++ sprechen (Sie sollten angeben, esp als __FUNCTION__ ist eine Nicht-Standard-Erweiterung), gibt es __FUNCDNAME__ und __FUNCSIG__ Symbole was du analysieren könntest


2
2017-11-03 11:48



Sie können den Funktionsnamen einschließlich des Klassennamens abrufen. Dies kann C-Typ-Funktionen verarbeiten.

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



Meine Lösung:

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

Ich arbeite für Visual C ++ 12.


1
2017-11-14 09:21



Hier ist eine Lösung basierend auf der __FUNCTION__ Makro- und C ++ - Vorlagen:

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

Hier ist ein Beispiel, wie dies für eine Logger-Klasse verwendet werden könnte

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);
  }
}

Die Ausgabe von Example::Run wird dann sein

Example: 0
Logger<Example>: 0

1
2018-01-22 12:29



Wenn Sie etwas benötigen, das den Klassennamen zur Kompilierzeit erzeugt, können Sie dazu C ++ 11 verwenden:

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

template<class T> T& classMacroImpl(const T* t);

Ich erkenne, dass das nicht dasselbe ist wie __FUNCTION__ aber ich habe diesen Beitrag gefunden, als ich nach einer Antwort wie dieser suchte. : D


1
2018-04-27 17:01