문제

템플릿 유형의 문자열 이름 (const char*)을 얻고 싶습니다. 불행히도 나는 RTTI에 액세스 할 수 없습니다.

template< typename T >
struct SomeClass
{
    const char* GetClassName() const { return /* magic goes here */; }
}

그래서

SomeClass<int> sc;
sc.GetClassName();   // returns "int"

이게 가능해? 나는 길을 찾을 수없고 포기하려고합니다. 도와 주셔서 감사합니다.

도움이 되었습니까?

해결책

아니요, 그리고 그것은 typeid와 신뢰할 수 없습니다. 컴파일러 구현에 의존하는 내부 문자열을 제공합니다. "int"와 같은 것은 "I"도 일반적입니다. int.

그건 그렇고, 당신이 원하는 것이 두 유형이 동일한 지 비교하는 경우 먼저 문자열로 변환 할 필요가 없습니다. 당신은 그냥 할 수 있습니다

template<typename A, typename B>
struct is_same { enum { value = false }; };

template<typename A>
struct is_same<A, A> { enum { value = true }; };

그리고 그렇게합니다

if(is_same<T, U>::value) { ... }

부스트는 이미 그러한 템플릿이 있으며 다음 C ++ 표준에는 std::is_same 도.

유형의 수동 등록

다음과 같은 유형을 전문화 할 수 있습니다.

template<typename> 
struct to_string {
    // optionally, add other information, like the size
    // of the string.
    static char const* value() { return "unknown"; }
};

#define DEF_TYPE(X) \
    template<> struct to_string<X> { \
        static char const* value() { return #X; } \
    }

DEF_TYPE(int); DEF_TYPE(bool); DEF_TYPE(char); ...

따라서 사용할 수 있습니다

char const *s = to_string<T>::value();

물론 유형을 알려지지 않은 경우 컴파일 시간 오류를 받으려면 기본 템플릿 정의를 제거 할 수도 있습니다 (전방 선언 만 유지). 나는 단지 완료를 위해 여기에 포함시켰다.

나는 이전에 Char Const*의 정적 데이터 멤버를 사용했지만, 그것들을 선언 할 곳 등의 질문과 같은 복잡한 문제를 일으킨다. 위와 같은 클래스 전문화는 문제를 쉽게 해결합니다.

GCC에 따라 자동

또 다른 방법은 컴파일러 내부에 의존하는 것입니다. GCC에서 다음은 합리적인 결과를 제공합니다.

template<typename T>
std::string print_T() {
    return __PRETTY_FUNCTION__;
}

반환 std::string.

std::string print_T() [with T = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]

약간 substr 마법이 혼합되어 있습니다 find 당신이 찾는 문자열 표현을 줄 것입니다.

다른 팁

정말 쉬운 솔루션 : someclass의 생성자에게 문자열 객체를 전달하는 것입니다.

예시:

#define TO_STRING(type) #type
SomeClass<int> s(TO_STRING(int));

간단히 저장하고 getClassName의 구현에 표시하십시오.

약간 더 복잡한 솔루션이지만 여전히 매우 쉽습니다.

#define DEC_SOMECLASS(T, name) SomeClass<T> name;  name.sType = #T; 

template< typename T >
struct SomeClass
{
    const char* GetClassName() const { return sType.c_str(); }
    std::string sType;
};


int main(int argc, char **argv)
{
    DEC_SOMECLASS(int, s);
    const char *p = s.GetClassName();

    return 0;
}

템플릿 비 유형 솔루션 :

또한 자신의 유형 ID를 만들고 ID 및 문자열 표현으로 전환 할 함수를 가질 수 있습니다.

그런 다음 유형을 템플릿이 아닌 매개 변수로 선언 할 때 ID를 전달할 수 있습니다.

template< typename T, int TYPEID>
struct SomeClass
{
    const char* GetClassName() const { return GetTypeIDString(TYPEID); }
};


...

SomeClass<std::string, STRING_ID> s1;
SomeClass<int, INT_ID> s2;

당신은 이와 같은 것을 시도 할 수 있습니다 (이것은 내 머리 꼭대기에서 떨어져 있기 때문에 컴파일 오류 등이있을 수 있습니다.)

template <typename T>
const char* GetTypeName()
{
    STATIC_ASSERT(0); // Not implemented for this type
}

#define STR(x) #x
#define GETTYPENAME(x) str(x) template <> const char* GetTypeName<x>() { return STR(x); }

// Add more as needed
GETTYPENAME(int)
GETTYPENAME(char)
GETTYPENAME(someclass)

template< typename T >
struct SomeClass
{
    const char* GetClassName() const { return GetTypeName<T>; }
}

이것은 당신이 추가하는 모든 유형에 대해 작동합니다. GETTYPENAME(type) 라인. 관심있는 유형을 수정하지 않고 작동하며 내장 및 포인터 유형에서 작동한다는 이점이 있습니다. 사용하려는 모든 유형에 대한 선이 있어야한다는 별개의 단점이 있습니다.

내장 된 RTTI를 사용하지 않으면 Brian R. Bondy의 답변이나 Dirkgently 's Will이 작동하는 정보를 직접 추가해야합니다. 내 대답과 함께 해당 정보를 추가 할 세 가지 위치가 있습니다.

  1. 객체 생성 시간을 사용하여 SomeClass<int>("int")
  2. Dirkgently의 Compile-Time RTTI 또는 가상 함수를 사용하는 클래스에서
  3. 내 솔루션을 사용하여 템플릿을 사용합니다.

세 가지 모두 효과가있을 것입니다. 상황에서 가장 적은 유지 보수 두통으로 끝날 수있는 문제 일뿐입니다.

RTTI에 액세스 할 수 없으므로 typeid (t) .name ()를 사용할 수 없습니까? 그것이 컴파일러의 도움으로 그것을하는 유일한 방법이기 때문입니다.

유형이 고유 한 이름을 갖는 것이 매우 중요합니까, 아니면 이름이 어떻게 든 지속될 것입니까? 그렇다면 코드에 선언 된 클래스 이름보다 더 강력한 것을 제공하는 것을 고려해야합니다. 다른 네임 스페이스에 넣어 두 개의 클래스에 동일한 자격이없는 이름을 줄 수 있습니다. Windows의 두 개의 다른 DLL에 동일한 이름 (네임 스페이스 자격 포함)을 가진 두 개의 클래스를 넣을 수도 있으므로 이름에도 DLL을 식별해야합니다.

그것은 모두 당신이 끈으로 무엇을할지에 달려 있습니다.

약간의 마법을 직접 추가 할 수 있습니다. 같은 것 :

#include <iostream>

#define str(x) #x
#define xstr(x) str(x)
#define make_pre(C) concat(C, <)
#define make_post(t) concat(t, >)

#define make_type(C, T) make_pre(C) ## make_post(T)
#define CTTI_REFLECTION(T, x)  static std::string my_typeid() \
                               { return xstr(make_type(T, x)); }


// the dark magic of Compile Time Type Information (TM)
#define CTTI_REFLECTION(x)  static const char * my_typeid() \
                                  { return xstr(make_type(T, x)); }

#define CREATE_TEMPLATE(class_name, type) template<> \
                                    struct class_name <type>{ \
                                        CTTI_REFLECTION(class_name, type) \
                                    }; 

// dummy, we'll specialize from this later
template<typename T> struct test_reflection;

// create an actual class
CREATE_TEMPLATE(test_reflection, int)

struct test_reflection {
  CTTI_REFLECTION(test_reflection)
};

int main(int argc, char* argv[])
{
    std::cout << test_reflection<int>::my_typeid();
}

나는 검사관을 만들 것이다 static 기능 (따라서 비const).

아니, 죄송합니다.

int에서 사용하려고하면 RTTI가 컴파일되지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top