最近在stackoverflow看到一个问题: Is it possible to print a variable's type in standard C++? 觉得挺有意思, 整理下供大家阅读.
本文介绍了获取对象类型的两个宏:
__typeofObj(obj)获取求解对象定义时的类型
int&& r = 2;
__cs(__typeofObj(r)); // r=int&&
-
__typeofExpr(obj)获取求解对象做为表达式时的类型和值类别如下定义的
r类型为int&&, 但r在做为表达式时的值类别是左值,所以推导出的类型是int&
int&& r = 2;
__cs(__typeofObj(r)); // r=int&&
__cs(__typeofExpr(r)); // r=int&
可以在c++11及以上版本中使用.
c++工具函数 - 如何得到类型字符串
__FUNCPRT__
使用宏__FUNCSIG__ (vc++)或者__PRETTY_FUNCTION__ (gcc, clang)来实现这个功能.
#if defined(_MSC_VER)
#define __FUNCPRT__ __FUNCSIG__
#else
#define __FUNCPRT__ __PRETTY_FUNCTION__
#endif
为兼容编译器, 如上处理得到__FUNCPRT__.
decltype(obj) 或 decltype((obj))
template <class T>
const char* typeInfoGet() {
return __FUNCPRT__;
}
然后为了获取对象的类型字符串, 需要通过上面的typeInfoGet模板, 即typeInfoGet<decltype(obj)>或typeInfoGet<decltype((obj))>:
decltype(obj)获取求解对象定义时的类型decltype((obj))获取求解对象做为表达式时的类型
对于A fn21(A a)函数, 通过typeInfoGet<decltype(fn21)获取到的__FUNCPRT__的字符串内容是: const char* typeInfoGet() [with T = A(A)], 对于const char* typeInfoGet() [with T = 这36个字符以及后面的]字符,是不需要的, 即s.substr(36, s.size() - 37)只需要A(A)字符串.
__typeofObj(obj) 和 __typeofExpr(obj)
最后通过自定义的宏: __typeofObj(obj)和__typeofExpr(obj), 这两个宏是为了简化获取类型字符串的手写代码量, 利用宏参数字符串即#obj, 结合typeStr函数完成类型字符串获取.
#include <iostream>
using namespace std;
#if defined(_MSC_VER)
#define __FUNCPRT__ __FUNCSIG__
#else
#define __FUNCPRT__ __PRETTY_FUNCTION__
#endif
template <class T>
const char* typeInfoGet() {
return __FUNCPRT__;
}
std::string typeStr(const char* cstr, const char* name) {
std::string s(cstr);
std::string n(name);
return n.append("=").append(s.substr(36, s.size() - 37));
}
#define __typeofObj(obj) typeStr(typeInfoGet<decltype(obj)>(), #obj);
#define __typeofExpr(obj) typeStr(typeInfoGet<decltype((obj))>(), #obj);
#define __cs(expr) cout << "\n" << expr;
struct A {
A() { cout << " 默认构造;"; }
};
A fn21(A a) { return a; }
int main() {
__cs(__typeofObj(fn21)); // fn21=A(A)
int a = 2;
__cs(__typeofObj(a)); // a=int
__cs(__typeofExpr(a)); // a=int&
__cs(__typeofExpr(std::move(a))); // std::move(a)=int&&
int&& r = 2;
__cs(__typeofObj(r)); // r=int&&
__cs(__typeofExpr(r)); // r=int&
return 0;
}