2012-01-17 10 views
2

私は基本的にXMLファイルに値を書き込むC++のテンプレート関数を持っていますが、検証のために変数型とその値を書き出したいと思います。私は現在、intのための素晴らしい作品typeid(T).name()doubleなどを使用していますが、それはいつもよりも「文字列」以上の意味のある何かを書き出すように私はchar配列とstd::stringのための特別なケースをしたい:C++テンプレートT、型の検出は文字列の形式

class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > 

または

char const [2] 

どのように私はこれをエレガントな方法で行うことができますか?

私のコード(削減)、このようになります(ない関数はテンプレートだけである)

template <typename T> bool SetValue(const std::string &sectionName, const std::string &valueName, const T &value) 
    { 
     myXMl->AddAttribute(TYPE_DEF,typeid(T).name()); 
     return true; 
    } 

答えて

10

あなたはこのために特性クラスを使用することができます。

template<class T> 
class type_name { 
public: 
    static std::string get() { return typeid(T).name(); } 
}; 

このテンプレートは、default-を実装場合。今、あなたは特別な名前を持っていなければならないタイプのためにそれを特化することができます

template<> 
class type_name<std::string> { 
public: 
    static std::string get() { return "string"; } 
}; 

template<> 
class type_name<const char *> { 
public: 
    static std::string get() { return "string"; } 
}; 

template<int N> 
class type_name<const char[N]> { 
public: 
    static std::string get() { return "string"; } 
}; 

あなたのコードは次のようになります。

template <typename T> bool SetValue(const std::string &sectionName, 
            const std::string &valueName, const T &value) 
    { 
     myXMl->AddAttribute(TYPE_DEF, type_name<T>::get()); 
     return true; 
    } 
+0

シンプルでエレガントな1 –

+0

私は私が私のコードにこれを追加するにはどうすればよい、従わわからないんだけど?私は私のサンプルコードで質問を更新しました。 – Chris

+0

@Chris:あなたのコードに必要な変更を加えました。 –

4

あなたはシム関数の内部あなたのタイプをラップすることができます。これらの関数は実際には実行されないので、実際には定義する必要はありません。適切な関数を選択するためにオーバーロード解決を使用する宣言だけが必要なので、typeid()式で結果の型を取ることができます。

テンプレート関数は完全一致のためにのみ選択され、テンプレート以外の関数のオーバーロードは暗黙的な変換が可能です。

例:

#include <string> 
#include <iostream> 
#include <typeinfo> 

struct string{}; 

template <typename T> T shim(T); 
// Not needed, literals will be matched by (const char*) below 
// template <size_t S> string shim(const char (&)[S]); 
string shim(const char*); 
string shim(const std::string&); 

int main() 
{ 
    std::cout << typeid(shim(1.0)).name() << "\n" 
      << typeid(shim(true)).name() << "\n" 
      << typeid(shim(0)).name() << "\n" 
      << typeid(shim((void *)NULL)).name() << "\n" 
      << typeid(shim("hello there")).name() << "\n" 
      << typeid(shim((const char*)"hello there")).name() << "\n" 
      << typeid(shim(std::string("hello there"))).name() << std::endl; 
} 
+0

OPのテンプレートが 'char [N]'でインスタンス化されている場合、そのfunctinoのリテラルではないので、 'char [N]'のバージョンが必要です。 'シム'が選択されます。 –

+0

はい、本当にありがとうございます。私はあなたのソリューションがより良いのが好きです:D 私は、オーバーロードを採用することであなたの能力を "強化"して、多くのテンプレートクラスを定義することを避けることができると思います。 – bronekk