12

は人間が理解できる型の名前を返さないためtypeid(T).name()、テンプレート引数の名前をクラステンプレートに出力したい場合、特にデバッグ中にはあまり役に立ちません。デバッグでこれを書きたいと思うことがよくあります。

print<Args...>(cout); //dump the names of all types to stdout!

そこで、クラス テンプレートの名前を表示するプリティ プリント ユーティリティを作成しています。まあ、いくつかのサンプル使用法を通してそれを理解するのはより簡単です:

print<int>(cout);               //prints int
print<int, double, char>(cout); //prints int, double, char
print<std::string>(cout);       //prints std::basic_string<char,  .. etc>
print<std::wstring>(cout);      //prints std::basic_string<wchar_t, .. etc>
print<X<int,Y<int>>>(cout);     //prints X<int, Y<int>>

内部的には、テンプレート引数として渡すtemplate_nameと返されるというクラス テンプレートを使用しています。ここでは、ユーザー クラス テンプレートごとに部分的に特化する方法を示します。"Y"Y<int>

#define DEFINE_TEMPLATE_NAME(template_type) \
template<typename ... Ts>\
struct template_name<template_type<Ts...>>\
{\
    static const char* name()\
    {\
        return #template_type;\
    }\
};

そして、ユーザーはこのマクロを使用してテンプレート クラスを次のように登録する必要があります。

DEFINE_TEMPLATE_NAME(std::basic_string);
DEFINE_TEMPLATE_NAME(std::vector);
DEFINE_TEMPLATE_NAME(X); //X is a class template
DEFINE_TEMPLATE_NAME(Y); //Y is a class template

特殊化はtemplate_name<template_type<Ts...>>のみの可変引数クラス テンプレートであるため、これは機能します。つまり、すべてのテンプレート パラメーターがtypesである限り、クラス テンプレートの名前が返されます。関数型とメンバー関数型も出力できます。

typedef void fun(int,int);

//lets use snl::name() which returns name instead of printing!
std::cout << snl::name<fun>();    //prints : void(int,int)
std::cout << snl::name<fun*>();   //prints : void(*)(int,int)

その他の詳細については、こちらの作業コードを参照してください。それはこれまでのところうまくいきます。

しかし今、私はこれを改善しており、型以外のテンプレート引数と混合テンプレート引数のサポートも追加したいと考えています:

template<int...>
struct Z{};

//non-type template arguments : 1,2,3
snd::print<Z<1,2,3>>(cout);  //should print Z<1,2,3>

//mixed template arguments : int, 100
snd::print<std::array<int,100>>(cout);  //should print std::array<int,100>

どうすればいいですか?そのようなクラステンプレートの名前とその引数を一般的に取得するにはどうすればよいですか?

4

1 に答える 1

6

これは「否定的な答え」で申し訳ありませんが(私はあなたの質問に賛成です)、残念ながらそれはできません。非型パラメーター ( 、 など) の同種のリストを受け入れるテンプレート クラスだけを考えても、次template<int, int>template<char, char, char>ような特殊化が必要になります。

template<typename T>
struct single_type
{
    // ...
};

template<typename U, template<U...> class C, U... Us>
struct single_type<C<Us...>>
{
    // ...
};

この特殊化は正当ですが、引数の型Uを推測できないため役に立ちません。int...最も一般的な型 ( 、など)のリテラルの統一リストに対して専用の特殊化を定義することはできますがchar...、混合引数のシーケンスは言うまでもなく、異質な型のシーケンスをカバーすることは依然として不可能です。

探しているものを実現するには、C++ がリフレクションをサポートするまで待つ必要があると思います。

于 2012-12-30T17:33:28.350 に答える