2010-12-19 15 views
41

C++でテンプレートを再生しているときに、typename Tをstringに変換する際に問題が発生しました。たとえば、:typenameをC++の文字列に変換する方法

template <typename T> 
class Matrix { 
    public: 
     Matrix() { 
      //my_type = string type of T. i.e. if T is char. I want my_type to be "char". 
     } 
    string my_type; 
} 

TをTとは何かを示す文字列に変換するにはどうすればよいですか。

注:私は周りを遊んでいるので、そのようなことが必要なときは心配しないでください。

答えて

41

これには組み込みの機構がありません。 typeid(T)::name()はいくつかの情報を与えることができますが、標準ではこの文字列を人間が読めるようにする必要はありません。それぞれのタイプごとに異なっています。 Microsoft Visual C++は人間が読める文字列を使用します。 GCCはそうではありません。

独自のシステムを構築することはできますが、例えば、形質に基づく。このようなもの:

// default implementation 
template <typename T> 
struct TypeName 
{ 
    static const char* Get() 
    { 
     return typeid(T).name(); 
    } 
}; 

// a specialization for each type of those you want to support 
// and don't like the string returned by typeid 
template <> 
struct TypeName<int> 
{ 
    static const char* Get() 
    { 
     return "int"; 
    } 
}; 

// usage: 
const char* name = TypeName<MyType>::Get(); 
+1

GCCは、Itanium ABI機能でデングルメントすることができる、Itanium ABIのマングルド名を提供します。 – Puppy

5

少なくとも、直接はできません。トークンまたは一連のトークンを文字列リテラルに変換する唯一の方法は、マクロ内でプリプロセッサの文字列演算子(#)を使用することです。

型を表す文字列リテラルを取得する場合は、おそらくマクロを使用してテンプレートをインスタンス化し、文字列型の型名を渡すことで、何かを書く必要があります。任意の一般的なアプローチで

1つの問題は、次の用途のために与えられるべき文字列:

Matrix<char> x; 
typedef char MyChar; 
Matrix<MyChar> y; 

xy両方が同じタイプであるが、一つは直接charを使用し、他方はのtypedefを使用しますMyChar

2

タイプが基本タイプの1つである場合は、タイプ名をstringにすることは不可能です。ユーザー定義タイプの場合はtypeid(my_type).name()を使用できます。また、#include <typeinfo>が必要です。 more info...

16

GCCでは、トリックを使用する必要があります。 cxxabi.h を使用して私はこの目的のために少しラッパーを書いた。

#include <string> 
#include <iostream> 
#include <iomanip> 
#include <typeinfo> 
#include <cxxabi.h> 

#define DEBUG_TYPE(x) do { typedef void(*T)x; debug_type<T>(T(), #x); } while(0) 

template<typename T> 
struct debug_type 
{ 
    template<typename U> 
    debug_type(void(*)(U), const std::string& p_str) 
    { 
     std::string str(p_str.begin() + 1, p_str.end() - 1); 
     std::cout << str << " => "; 
     char * name = 0; 
     int status; 
     name = abi::__cxa_demangle(typeid(U).name(), 0, 0, &status); 
     if (name != 0) { std::cout << name << std::endl; } 
     else { std::cout << typeid(U).name() << std::endl; } 
     free(name); 
    } 
}; 

二重祖父母が必要です。任意のタイプで動作します。

今、あなたはブーストのためにそれを使用することができます:: MPL:

DEBUG_TYPE((if_c<true, true_, false_>::type)); 

ますプリント:

if_c<true, true_, false_>::type => bool_<true> 
+0

これはItanium 64ビットのプロセッサ固有ではないでしょうか?これは他のアーキテクチャでも使えますか? – serup

3

回避策の道...

#define Tprint(x) print<x>(#x) 

template<typename T> 
void print (string ltype){ 
cout<<ltype<<" = "<<sizeof(T)<<endl; 
} 
+0

フォーマットが正しくない場合は、すみません。私の最初の投稿は、スタックフローです。 – user3071398

+2

'Tprint(T)'を実行すると、元の質問で与えられたテンプレートパラメータが 'T 'である場合、' T = 4'または何らかの数が得られることは確信しています。画面に書き込まれたTのタイプを取得しません。 –

0

あなたはC++ reflection libraryを使用することができます。したがって:

using namespace ponder; 

Class::declare<Matrix>(); 

std::string const& name = classByType<Matrix>().name(); 

これでクラスメンバーの見た目など、メタクラス情報を取得すると、他にもオプションがあります。その専門の生成

-2
template< typename From,typename To> 
static inline bool superConvert(const From& fromVar,To& toVar) 
{ 
    stringstream ss; 
    ss<<fromVar; 
    ss>>toVar; 
    if(ss.fail()) 
    { 
     return false; 
    } 
    else 
    { 
     From tempFrom; 
     stringstream ss; 
     ss<<toVar; 
     ss>>tempFrom; 
     if(tempFrom != fromVar) 
     { 
      return false; 
     } 
     else 
     { 
      return true; 
     } 
    } 
} 
+0

私はこれがどのように問題に関連しているのか分かりません。 –

+0

任意の型を文字列に変換することができます。 –

+0

質問に誤解があり、テンプレートで使用されている型の文字列名を取得しようとしています。本質的に 'std :: string type =" "'それは動作しません。 –

関連する問題