C++ typeid的可读形式?

C++ typeid的可读形式?,c++,c++11,typeid,C++,C++11,Typeid,是否有编译器以可读的方式返回类型名称(或提供该功能或工具的库)。基本上,我想要的是与您将在源代码中编写的类型表达式对应的字符串 typeid(var).name() 这就是你要找的。虽然不同的编译器的输出不同。。。例如,对于gcc而言,int的输出为i,对于无符号的为j。下面是一个小测试程序: #include <iostream> #include <typeinfo> struct A { virtual ~A() { } }; struct B : A { }

是否有编译器以可读的方式返回类型名称(或提供该功能或工具的库)。基本上,我想要的是与您将在源代码中编写的类型表达式对应的字符串

 typeid(var).name()
这就是你要找的。虽然不同的编译器的输出不同。。。例如,对于
gcc
而言,
int
的输出为
i
,对于
无符号的
j
。下面是一个小测试程序:

#include <iostream>
#include <typeinfo>

struct A { virtual ~A() { } };
struct B : A { };

class C { };
class D : public C { };

int main() {
  B b;
  A* ap = &b;
  A& ar = b;
  std::cout << "ap: " << typeid(*ap).name() << std::endl;
  std::cout << "ar: " << typeid(ar).name() << std::endl;

  D d;
  C* cp = &d;
  C& cr = d;
  std::cout << "cp: " << typeid(*cp).name() << std::endl;
  std::cout << "cr: " << typeid(cr).name() << std::endl;

  int e;
  unsigned f;
  char g;
  float h;
  double i;
  std::cout << "int:\t" << typeid(e).name() << std::endl;
  std::cout << "unsigned:\t" << typeid(f).name() << std::endl;
  std::cout << "char:\t" << typeid(g).name() << std::endl;
  std::cout << "float:\t" << typeid(h).name() << std::endl;
  std::cout << "double:\t" << typeid(i).name() << std::endl;
}
#包括
#包括
结构A{virtual~A(){};
结构B:A{};
C类{};
D类:公共C{};
int main(){
B B;
A*ap=&b;
A&ar=b;

std::cout下面是我为检查类型而编写的一个小类。如果需要,可以向其中添加更多类型。它不能检查数组类型、映射或任何过于高级的内容。如果需要,可以添加更多类型,甚至可以添加自己的自定义类型。这只是一个小示例

此外,getType函数是您要查找的。根据它匹配的类型,您可以自定义输出字符串。我省略了包含部分,因此对于该部分,您只需找到正确的包含文件,因为此库是我的较大库的一部分

/*页眉.hpp*/

class _cType
{
    public:
    _cType();
    ~_cType();

    template<class T, class U>
    static bool isSame(T &vl, U &vr);

    template<class T>
    static bool isInt(T &v);

    template<class T>
    static bool isUInt(T &v);           

    template<class T>
    static bool isFloat(T &v);

    template<class T>
    static bool isLong(T &v);

    template<class T>
    static bool isDouble(T &v);

    template<class T>
    static bool isBool(T &v);

    template<class T>
    static bool isString(T &v);

    template<class T>
    static bool isChar(T &v);

    template<class T>
    static std::string getType(T &v);

};

extern _cType Type;
class\u cType
{
公众:
_cType();
~_cType();
模板
静态布尔ISAME(T&vl、U&vr);
模板
静态噪声(T&v);
模板
静态布尔isUInt(T&v);
模板
静态bool isFloat(T&v);
模板
静态布尔伊斯隆(T&v);
模板
静态布尔值(T&v);
模板
静态布尔-伊斯布尔(T&v);
模板
静态弹簧(T&v);
模板
静态布尔伊斯卡尔(T&v);
模板
静态std::字符串getType(T&v);
};
外部类型;
/*source.cpp*/

_cType::_cType(){};


template<class T, class U>
bool _cType::isSame(T &vl, U &vr){
    return ( typeid(vl) == typeid(vr) );
}

template<class T>
bool _cType::isInt(T &v){
    return typeid(v) == typeid(int);
}

template<class T>
bool _cType::isUInt(T &v){
    return typeid(v) == typeid(unsigned int);
}    

template<class T>
bool _cType::isFloat(T &v){
    return typeid(v) == typeid(float);
}

template<class T>
bool _cType::isLong(T &v){
    return typeid(v) == typeid(long);
}

template<class T>
bool _cType::isDouble(T &v){
    return typeid(v) == typeid(double);
}

template<class T>
bool _cType::isBool(T &v){
    return typeid(v) == typeid(bool);
}

template<class T>
bool _cType::isString(T &v){
    return typeid(v) == typeid(std::string);
}

template<class T>
bool _cType::isChar(T &v){
    return typeid(v) == typeid(char);
}

template<class T>
std::string _cType::getType(T &v){

    if ( typeid(v) == typeid(int) ) return "int";    
    else if ( typeid(v) == typeid(unsigned int) ) return "unsigned int";
    else if ( typeid(v) == typeid(float) ) return "float";
    else if ( typeid(v) == typeid(long) ) return "long";
    else if ( typeid(v) == typeid(double) ) return "double";
    else if ( typeid(v) == typeid(char) ) return "char";
    else if ( typeid(v) == typeid(std::string) ) return "std::string";
    else if ( typeid(v) == typeid(bool) ) return "bool";
    else return std::string("User defined or unknown type: ") + typeid(v).name();
}

_cType::~_cType(){};

_cType Type;
\u cType::\u cType(){};
模板
布尔类型::ISNAME(T&vl、U&vr){
返回(typeid(vl)=typeid(vr));
}
模板
布尔类型::isInt(T&v){
返回typeid(v)=typeid(int);
}
模板
布尔类型::智能单元(T&v){
返回typeid(v)=typeid(无符号整数);
}    
模板
bool_cType::isFloat(T&v){
返回typeid(v)=typeid(float);
}
模板
bool_cType::isLong(T&v){
返回typeid(v)=typeid(long);
}
模板
bool_cType::isDouble(T&v){
返回类型ID(v)=类型ID(双);
}
模板
布尔类型::伊斯布尔(T&v){
返回typeid(v)=typeid(bool);
}
模板
bool_cType::isString(T&v){
返回typeid(v)=typeid(std::string);
}
模板
bool_cType::isChar(T&v){
返回typeid(v)=typeid(char);
}
模板
std::string _cType::getType(T&v){
如果(typeid(v)=typeid(int))返回“int”;
else if(typeid(v)=typeid(unsigned int))返回“unsigned int”;
否则如果(typeid(v)=typeid(float))返回“float”;
否则如果(typeid(v)=typeid(long))返回“long”;
否则如果(typeid(v)=typeid(double))返回“double”;
否则如果(typeid(v)=typeid(char))返回“char”;
else if(typeid(v)=typeid(std::string))返回“std::string”;
否则如果(typeid(v)=typeid(bool))返回“bool”;
否则返回std::string(“用户定义或未知类型:”)+typeid(v.name();
}
_cType::~\u cType(){};
_cType类型;

在搜索此问题时,我刚刚在boost库中找到了我需要的:

在我的例子中,它用于捕获异常:

try {
  //...
} catch (std::exception& e) {
  boost::core::scoped_demangled_name demangled(typeid(e).name());
  std::cerr << "ERROR: " << demangled.get() << ": " << e.what() << std::endl;
}
试试看{
//...
}捕获(标准::异常&e){
boost::core::scoped_demangled_name demangled(typeid(e).name());

STR::CURR < P>回答您的问题的字母(其他答案回答它的意图),最简单的答案是VisualC++提供“未修饰”(未加密的)名称作为输出,用于<代码> STD::Type OnIf:::(或)代码>,同时隐藏编译器扩展后的实际、被损坏的类型<代码> STD::Type On:Fix:RavyNAME.()
;CPPReference还提到IBM和Oracle提供了demangled,人类可读的名称,但我对他们的编译器没有经验,因此我自己也不能说这一说法是否准确。

可能有编译器特定的工具来demangle'typeid().name()返回的类型名称`。例如,对于GCC,请参见。@steffen我知道我可以为特殊情况编写自己的代码(从我的代码开始),但有时我在阅读其他人的代码(我并没有接触过的人)时,类型表达式很复杂,或者他们使用“自动”,我不知道他们在“说”什么.BTW,链接中的PRETTY_函数是解决方案的一部分。@FredFinkle:好的,我明白了……在这种情况下,您可以做的是比较
typeid()的返回值
到您假定的类或类型的某些值。或代码中出现的任何类。@JohannesD demangle看起来很完美,但当我编译示例代码时,它会编译,但不会产生相同的输出。事实上,它不会打印任何内容,除了字符串“std::bad\u exception”谢谢。@JohannesD gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demanling.html中的示例有一个bug。行--realname=abi::uu cxa_demangle(e.what(),0,0和status)--应该类似于--realname=abi:u cxa demangle(typeid(e.name(),0,0和status)。有了这个更改,它就完美地工作了。e.what()异常的解释不是一个损坏的(或其他)名称。另请参见:如果它类似于“在
auto foo=bar();
”中的foo类型,那么一个选项(如果重建时间足够便宜)是强制执行错误,例如
struct{}_=foo;
,这样错误消息就足够有用,可以告诉您
foo
@LucDanton的类型,但这很麻烦。而且,由于我想做的大多数时候都不涉及“auto”,因此构建一个错误消息有用的案例并不总是那么容易。