8

decltypeC++ マクロで評価できる方法はありますか? 私の主な動機は、 の型を判別thisして文字列に変換できるマクロを作成することです。

使用できない場合decltype、クラス宣言内で使用されるマクロがクラスの型を文字列として取得できる他の方法はありますか?

4

2 に答える 2

7

decltypeC++ マクロで評価できる方法はありますか?

いいえ、マクロは の decltypeに厳密に評価されるためです。

私の知る限り、クラスの名前をマクロとして取得する方法はありません。そのような方法は、コンパイラによって生成されたマクロによってサポートされる必要があります。

ただし、 を使用typeidしてマングルされた名前 (厳密に言えば、実装定義の表現) を取得し、コンパイラ固有のツールを使用して、そこからデマングルされた名前を取得できます。

たとえば、GCC はこれを行うためのデマングリング ライブラリを提供しています。

最小限の例を次に示しonline demoます。

#define THIS_CLASS_NAME() demangled(typeid(*this).name())

std::string demangled(char const* tname) {
    std::unique_ptr<char, void(*)(void*)>
        name{abi::__cxa_demangle(tname, 0, 0, nullptr), std::free};
    return {name.get()};
}

使用法:

namespace foo {
    template <typename T>
    struct bar {
        bar() { std::cout << THIS_CLASS_NAME() << '\n'; }
    };
}

int main() {
    foo::bar<int> b;
}

収量:

foo::bar<int>
于 2013-07-08T10:33:05.670 に答える
6

マクロはコードがコンパイルされる前に展開されるため、残念ながらマクロには型の概念がありません。

ただし、必要に応じて、代わりに特性クラスを使用できる場合があります。理論的には、RTTI や typeid よりも少し効率的で移植性がありますが、明示的に指定した型に対してのみ機能します。例えば:

template <typename T>
struct Traits
{
    static const char * TYPE_NAME;
};
// Generic definition as a fall-back:
template <typename T> const char * Traits<T>::TYPE_NAME = "unknown";

// Explicit definitions
template < > const char * Traits< int >::TYPE_NAME = "int";
template < > const char * Traits< float >::TYPE_NAME = "float";
template < > const char * Traits< ExampleClass >::TYPE_NAME = "ExampleClass";

明示的な定義は少し面倒なので、マクロを作成して読みやすくすることができます。

#define DECLARE_TYPE_TRAIT(name) template < > const char * Traits<name>::TYPE_NAME = #name;

DECLARE_TYPE_TRAITS(int)
DECLARE_TYPE_TRAITS(float)
DECLARE_TYPE_TRAITS(ExampleClass)

コードで traits クラスを使用するのは非常に簡単です。検索したいタイプの特性テンプレートをインスタンス化し、TYPE_NAME メンバーにアクセスするだけです。

int foo;
ExampleClass blah;

cout << Traits<decltype(foo)>::TYPE_NAME << endl;
cout << Traits<decltype(blah)>::TYPE_NAME << endl;
于 2013-07-08T11:02:19.650 に答える