2010-12-19 6 views
41

C++의 템플릿을 가지고 놀면서 typename T를 string으로 변환 할 때 문제가 발생했습니다. 예 :typename T를 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 기능으로 디맹 글트 될 수있는 아이 늄 ABI 맹 글링 된 이름을 제공합니다. – Puppy

5

적어도 직접적으로는 할 수 없습니다. 토큰 또는 일련의 토큰을 문자열 리터럴로 변환하는 유일한 방법은 전 처리기의 문자열 화 연산자 (#)를 매크로 내부에서 사용하는 것입니다.

형식을 나타내는 문자열 리터럴을 얻으려면 매크로를 사용하여 서식 파일을 인스턴스화하고 문자열 형식의 이름을 전달하는 등 직접 작성해야합니다. 다음과 같은 용도로 제공되어야 하는지를 문자열 : 어떤 일반적인 접근 방식

하나의 문제는

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

모두 xy이 같은 유형이지만, 하나는 직접 char를 사용하고 다른 하나는 형식 정의를 사용 MyChar.

2

유형이 기본 유형 중 하나 인 경우 유형 이름을 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)'를 쓰면, 원래 질문에 주어진 템플릿 매개 변수 인'Tprint (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 = ""'만이 작동하지 않습니다. –

관련 문제