web-dev-qa-db-ja.com

C ++に__CLASS__マクロはありますか?

関数名を与える__CLASS__マクロに似たクラス名を与えるC++の__FUNCTION__マクロはありますか

85
mortal

最も近いのはtypeid(your_class).name()を呼び出すことですが、これによりコンパイラ固有のマングル名が生成されます。

クラス内で使用するには、単にtypeid(*this).name()

60
Aleksei Potov

typeid(*this).name()の使用に関する問題は、静的メソッド呼び出しにthisポインターがないことです。マクロ___PRETTY_FUNCTION___は、静的関数およびメソッド呼び出しのクラス名を報告します。ただし、これはgccでのみ機能します。

マクロスタイルのインターフェイスを使用して情報を抽出する例を次に示します。

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

マクロ___METHOD_NAME___は<class>::<method>()という形式の文字列を返し、___PRETTY_FUNCTION___から得られるものから戻り値の型、修飾子、引数を切り取ります。

クラス名のみを抽出するものについては、クラスが存在しない状況をトラップするように注意する必要があります。

_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__)
_
64
Andrew Prock

未だに。 (__class__はどこかで提案されていると思います)。 __PRETTY_FUNCTION__からクラス部分を抽出することもできます。

boost :: typeindex を提案したいと思います。これは、Scott Meyerの「Effective Modern C++」から学んだ基本的な例です。

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

「g ++ --std = c ++ 14」でコンパイルすると、以下が生成されます

出力

テンプレートタイプを印刷する場合は、簡単です。

T =ダブル

オブジェクトインスタンスから取得するには、decltypeを使用します。

fbのタイプはfoo_barです

9
Spacemoose

__PRETTY_FUNCTION__には名前空間も含まれていますが、十分です。つまり、namespace::classname::functionnameまで__CLASS__ 利用可能です。

7
vaibhav

コンパイラがたまたまg++そして、あなたは__CLASS__クラスを含む現在のメソッド名を取得する方法が必要なため、__PRETTY_FUNCTION__が役立つはずです(info gcc、セクション5.43文字列としての関数名)。

3
ndim

MS C++を使用している場合(特に__FUNCTION__は非標準の拡張子です)、 __FUNCDNAME__および__FUNCSIG__シンボル 解析可能

2
Ruben Bartelink

私の解決策:

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

私はVisual C++ 12で働いています。

1

クラス名を含む関数名を取得できます。これにより、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
Charles.Lee

コンパイル時にクラス名を実際に生成するものが必要な場合は、C++ 11を使用してこれを実行できます。

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

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

これは__FUNCTION__と同じではないことを認識していますが、このような答えを探しているときにこの投稿を見つけました。 :D

1
Jon Thompson

__FUNCTION__マクロと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();
}

これをロガークラスに使用する方法の例を次に示します

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

Example::Runの出力は次のようになります

Example: 0
Logger<Example>: 0
1
Sven Vranckx

Msvcおよびgccでも動作します

#ifdef _MSC_VER
#define __class_func__ __FUNCTION__
#endif

#ifdef __GNUG__
#include <cxxabi.h>
#include <execinfo.h>
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
0
Costa

これは、ポインターのコストを支払う意思がある場合に非常にうまく機能します。

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__ ) {};
};
0
Robert Basler