是否可能在标准变量中打印变量的类型C++?
在C++中有typeid、typeof等方法可以让我们获取类型信息,但获取到的结果是不存在引用和 cv 限定符的。比如下面一段代码:
const int ia = 10;
cout << "type: " << typeid(ia).name() << endl;
// 输出:type: int
这并不是我们想要的结果,我们想要的输出是 const int
。而究竟是否可能在标准变量中打印变量的类型呢?
本文参考《Is it possible to print a variable’s type in standard C++?》
在 Stack Overflow 上给出了几种回答,这里贴出大神给出了 type_name 方法
方案一:
template <class T>
constexpr std::string_view
type_name()
{
using namespace std;
#ifdef __clang__
string_view p = __PRETTY_FUNCTION__;
return string_view(p.data() + 34, p.size() - 34 - 1);
#elif defined(__GNUC__)
string_view p = __PRETTY_FUNCTION__;
# if __cplusplus < 201402
return string_view(p.data() + 36, p.size() - 36 - 1);
# else
return string_view(p.data() + 49, p.find(';', 49) - 49);
# endif
#elif defined(_MSC_VER)
string_view p = __FUNCSIG__;
return string_view(p.data() + 84, p.size() - 84 - 7);
#endif
}
方案二:
template <typename T>
constexpr auto type_name() noexcept {
std::string_view name = "Error: unsupported compiler", prefix, suffix;
#ifdef __clang__
name = __PRETTY_FUNCTION__;
prefix = "auto type_name() [T = ";
suffix = "]";
#elif defined(__GNUC__)
name = __PRETTY_FUNCTION__;
prefix = "constexpr auto type_name() [with T = ";
suffix = "]";
#elif defined(_MSC_VER)
name = __FUNCSIG__;
prefix = "auto __cdecl type_name<";
suffix = ">(void) noexcept";
#endif
name.remove_prefix(prefix.size());
name.remove_suffix(suffix.size());
return name;
}
将以上两个函数分别命令为 type_name1
与 type_name2
简单的进行以下测试:
const int cia = 10;
const void* cvp = &cia;
cout << "type: " << type_name1<decltype(cia)>() << "\t" << type_name2<decltype(cia)>() << endl;
cout << "type: " << type_name1<decltype(cvp)>() << "\t" << type_name2<decltype(cvp)>() << endl;
/* 输出结果
type: <const int <const int
type: <const void* <const void*
*/
可以看到,type_name 可以很完美的输出类型信息。
下面再给出一些变量,我们对比以下 typeid 与 tpye_name 的输出结果。
这里我们先给出一些类型的定义,并使用 typeid 方法尝试输出他们的类型:
int ia = 10; // 普通变量
const int* cp_i = &ia; // 常量指针 const point
const int& clr_ia = ia; // 常量左值引用 const lvalue reference
int&& rr_ia = ia + 10; // 右值引用 "right value" reference
const int&& cr_ca = ia + 10; // 常量右值引用 const rvalue reference
cout << typeid(ia).name() << endl;
cout << typeid(cp_i).name() << endl;
cout << typeid(clr_ia).name() << endl;
cout << typeid(rr_ia).name() << endl;
cout << typeid(cr_ca).name() << endl;
运行结果如图:
我们可以看到最终输出的结果中都只是最基本的类型信息,是删除了变量自身的引用类型,与cv限定符类型后的结果。
而通过 type_name 获取类型信息时就可以完成的输出类型信息。
int ia = 10; // 普通变量
int* const p = &ia; // 指针常量
const int* cp_i = &ia; // 常量指针 const point
const int& clr_ia = ia; // 常量左值引用 const lvalue reference
int&& rr_ia = ia + 10; // 右值引用 "right value" reference
const int&& cr_ca = ia + 10; // 常量右值引用 const rvalue reference
cout << type_name1<decltype(ia)>() << "\t" << type_name1<decltype(ia)>() << endl;
cout << type_name1<decltype(p)>() << "\t" << type_name1<decltype(p)>() << endl;
cout << type_name1<decltype(cp_i)>() << "\t" << type_name1<decltype(cp_i)>() << endl;
cout << type_name1<decltype(clr_ia)>() << "\t" << type_name1<decltype(clr_ia)>() << endl;
cout << type_name1<decltype(rr_ia)>() << "\t" << type_name1<decltype(rr_ia)>() << endl;
cout << type_name1<decltype(cr_ca)>() << "\t" << type_name1<decltype(cr_ca)>() << endl;
可以看到对于引用类型可以完美的输出,而对于cv限定的变量类型也能很好的输出其类型,比如如下的volatile const类型变量:
volatile const int value = 10;
cout << type_name1<decltype(value)>() << "\t" << type_name1<decltype(value)>() << endl;
还没有评论,来说两句吧...