Подтвердить что ты не робот

Как преобразовать typename T в строку в С++

Во время игры с шаблонами в С++ я столкнулся с проблемой преобразования typename T в строку. Например:

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.

Примечание: я просто играю, поэтому, пожалуйста, не беспокойтесь о том, когда это может понадобиться.

4b9b3361

Ответ 1

Для этого нет встроенного механизма. typeid(T)::name() может дать некоторую информацию, но стандарт не позволяет этой строке быть удобочитаемым человеком; просто для каждого типа. Microsoft Visual С++ использует удобочитаемые строки; 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();

Ответ 2

Для 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);
    }
};

Требуется двойной родительский элемент. Работает с любым типом.

Теперь вы можете использовать его для boost:: mpl:

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

напечатает:

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

Ответ 3

Вы не можете, по крайней мере, не напрямую. Единственный способ конвертировать токен или серию токенов в строковый литерал - это использовать оператор стропоризации препроцессора (#) внутри макроса.

Если вы хотите получить строковый литерал, представляющий тип, вам придется что-то написать самостоятельно, возможно, используя макрос, чтобы создать экземпляр шаблона и передать ему строковое имя типа.

Одной из проблем с любым общим подходом является: какая строка должна быть указана для следующих целей:

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

Оба x и y имеют один и тот же тип, но один использует char напрямую, а другой использует typedef MyChar.

Ответ 4

обходной путь...

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

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

Ответ 5

Невозможно получить имя типа в string, если тип является одним из базовых типов. Для пользовательских типов вы можете использовать typeid(my_type).name(). Также вам нужно #include <typeinfo>:) подробнее...

Ответ 6

Вы можете использовать библиотеку отражений С++. Итак:

using namespace ponder;

Class::declare<Matrix>();

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

Это дает вам и другие параметры, как только вы получите информацию о метаклассе, например, посмотрите, что представляют члены класса.

Ответ 7

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;
        }
    }
}