最近在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;
}