如何在 c + + 中将类型名 T 转换为字符串

在使用 c + + 中的模板时,我遇到了一个将类型名 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 是什么。

注意: 我只是随便玩玩,所以请不要担心什么时候可能需要这样的东西。

100247 次浏览

你不能,至少不能直接说。将令牌或一系列令牌转换为字符串文字的唯一方法是在宏中使用预处理器的字符串化操作符(#)。

如果希望获得表示类型的字符串文本,则必须自己编写一些内容,可能需要使用宏来实例化模板并将字符串化类型名传递给它。

任何一般方法的一个问题是: 应该为下列用途提供什么字符串:

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

xy都是相同的类型,但是一个直接使用 char,另一个使用 typedef MyChar

如果类型是基类型之一,则不可能在 string中获得类型的名称。对于用户定义的类型,可以使用 typeid(my_type).name()。你也需要 #include <typeinfo>:) 更多信息。

这里没有内置的机制。

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();

对于海湾合作委员会,你必须使用一个技巧。使用 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>

变通的方法..。

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


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

你可以使用 C + + 反射库,所以:

using namespace ponder;


Class::declare<Matrix>();


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

一旦您拥有了元类信息,这也为您提供了其他选项,比如查看类成员是什么。

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