2012-01-25 32 views
3

標準的な方法は、いくつかのテンプレート黒い魔法を使うか、何らかの標準ライブラリ関数を使ってクラスの名前を得るためのものですか?typeid(T).name()の代わりにC++ 11?

+4

いいえ、ありません。 – Managu

+1

それは標準的な方法です。 – spraff

+1

@ spraffの場合、名前の表現は標準ではありません。 –

答えて

4

私は非常に便利な関数プロトタイプのきれいな印刷見つけたら:GCCで

を、PRETTY_FUNCTIONは、型関数のシグネチャだけでなく、その裸の名前が含まれています。テンプレートクラスの例えば

か、クラス名を取得する関数がC文字列として展開:

template<typename T> 
class Vector { 
    void foo(int i) { 
    cout << __PRETTY_FUNCTION__ << endl; 
    } 
}; 

クラスをインスタンス化していた場合はこれがあなたに

void Vector<double>::foo(int) 

のようなものを与えるだろう例えば、ダブルス。しかし、それはあなたにもユーザー定義型を与えます。

あまりファンシーではありませんが、その用途があります。

+5

'__PRETTY_FUNCTION__'はGCCの拡張です。 –

+1

まだ標準的な方法ではありませんが、名前は本当にかわいいです。 –

7

ありませんが、あなたは1を作ることができる:

template<class T> struct meta { 
    static const std::string& get_name() {return T::class_name;} 
}; 

、その後、いずれかのクラスに静的メンバclass_nameを追加します。

class MyClass { 
public: 
    static const std::string class_name("MyClass"); 
}; 

またはメタを専門:

template<> struct meta<int> { 
    static const std::string class_name("int"); 
    static const std::string& get_name() {return class_name;} 
}; 

(これを簡単にするためのマクロがあります)

#define specialize_meta(name) template<>struct meta<name>{static const std::string class_name(#name); static const std::string& get_name() {return class_name;} }; 
specialize_meta(double); 

、その後、メタテンプレートを使用します。あなた本当には狡猾な取得したい場合

int main() { 
    std::cout << meta<int>::get_name(); 
} 

を、あなたも機能のバージョンを作ることができるが、これらは(明らかに)専門なければなりません。

void foo(int) {} //function in question 
template<class T, T& a> struct metafunc; //dont define generic. 
template<decltype(foo), &foo> struct metafunc { //specialization 
    static const std::string func_name("void foo(int)"); 
} 
+1

すべてが 'std :: string'の代わりに' std :: string const& 'を返した場合、はるかに少ないコピーしか存在しません。 : - ]また、 'meta <> :: get_name()'は静的でなければなりません。 – ildjarn

+0

@ildjarn: 'class_name'のインプリメンタは静的な' std :: string'メンバではなく、より複雑な文字列を完全な関数でアセンブルできるように、コピーを返すようにしました。しかし、私はユースケースを思いつくことができませんでしたので、私はあなたの提案に行ってきました。 –

+0

これは、対象クラスでいくつかの作業が必要です。私はそんなことはできません。 –

関連する問題