是否可能在标准变量中打印变量的类型C++?

左手的ㄟ右手 2023-01-11 09:19 170阅读 0赞

在C++中有typeid、typeof等方法可以让我们获取类型信息,但获取到的结果是不存在引用和 cv 限定符的。比如下面一段代码:

  1. const int ia = 10;
  2. cout << "type: " << typeid(ia).name() << endl;
  3. // 输出:type: int

这并不是我们想要的结果,我们想要的输出是 const int 。而究竟是否可能在标准变量中打印变量的类型呢?
本文参考《Is it possible to print a variable’s type in standard C++?》


在 Stack Overflow 上给出了几种回答,这里贴出大神给出了 type_name 方法

方案一:

  1. template <class T>
  2. constexpr std::string_view
  3. type_name()
  4. {
  5. using namespace std;
  6. #ifdef __clang__
  7. string_view p = __PRETTY_FUNCTION__;
  8. return string_view(p.data() + 34, p.size() - 34 - 1);
  9. #elif defined(__GNUC__)
  10. string_view p = __PRETTY_FUNCTION__;
  11. # if __cplusplus < 201402
  12. return string_view(p.data() + 36, p.size() - 36 - 1);
  13. # else
  14. return string_view(p.data() + 49, p.find(';', 49) - 49);
  15. # endif
  16. #elif defined(_MSC_VER)
  17. string_view p = __FUNCSIG__;
  18. return string_view(p.data() + 84, p.size() - 84 - 7);
  19. #endif
  20. }

方案二:

  1. template <typename T>
  2. constexpr auto type_name() noexcept {
  3. std::string_view name = "Error: unsupported compiler", prefix, suffix;
  4. #ifdef __clang__
  5. name = __PRETTY_FUNCTION__;
  6. prefix = "auto type_name() [T = ";
  7. suffix = "]";
  8. #elif defined(__GNUC__)
  9. name = __PRETTY_FUNCTION__;
  10. prefix = "constexpr auto type_name() [with T = ";
  11. suffix = "]";
  12. #elif defined(_MSC_VER)
  13. name = __FUNCSIG__;
  14. prefix = "auto __cdecl type_name<";
  15. suffix = ">(void) noexcept";
  16. #endif
  17. name.remove_prefix(prefix.size());
  18. name.remove_suffix(suffix.size());
  19. return name;
  20. }

将以上两个函数分别命令为 type_name1type_name2 简单的进行以下测试:

  1. const int cia = 10;
  2. const void* cvp = &cia;
  3. cout << "type: " << type_name1<decltype(cia)>() << "\t" << type_name2<decltype(cia)>() << endl;
  4. cout << "type: " << type_name1<decltype(cvp)>() << "\t" << type_name2<decltype(cvp)>() << endl;
  5. /* 输出结果
  6. type: <const int <const int
  7. type: <const void* <const void*
  8. */

可以看到,type_name 可以很完美的输出类型信息。


下面再给出一些变量,我们对比以下 typeid 与 tpye_name 的输出结果。

这里我们先给出一些类型的定义,并使用 typeid 方法尝试输出他们的类型:

  1. int ia = 10; // 普通变量
  2. const int* cp_i = &ia; // 常量指针 const point
  3. const int& clr_ia = ia; // 常量左值引用 const lvalue reference
  4. int&& rr_ia = ia + 10; // 右值引用 "right value" reference
  5. const int&& cr_ca = ia + 10; // 常量右值引用 const rvalue reference
  6. cout << typeid(ia).name() << endl;
  7. cout << typeid(cp_i).name() << endl;
  8. cout << typeid(clr_ia).name() << endl;
  9. cout << typeid(rr_ia).name() << endl;
  10. cout << typeid(cr_ca).name() << endl;

运行结果如图:
在这里插入图片描述
我们可以看到最终输出的结果中都只是最基本的类型信息,是删除了变量自身的引用类型,与cv限定符类型后的结果。

而通过 type_name 获取类型信息时就可以完成的输出类型信息。

  1. int ia = 10; // 普通变量
  2. int* const p = &ia; // 指针常量
  3. const int* cp_i = &ia; // 常量指针 const point
  4. const int& clr_ia = ia; // 常量左值引用 const lvalue reference
  5. int&& rr_ia = ia + 10; // 右值引用 "right value" reference
  6. const int&& cr_ca = ia + 10; // 常量右值引用 const rvalue reference
  7. cout << type_name1<decltype(ia)>() << "\t" << type_name1<decltype(ia)>() << endl;
  8. cout << type_name1<decltype(p)>() << "\t" << type_name1<decltype(p)>() << endl;
  9. cout << type_name1<decltype(cp_i)>() << "\t" << type_name1<decltype(cp_i)>() << endl;
  10. cout << type_name1<decltype(clr_ia)>() << "\t" << type_name1<decltype(clr_ia)>() << endl;
  11. cout << type_name1<decltype(rr_ia)>() << "\t" << type_name1<decltype(rr_ia)>() << endl;
  12. cout << type_name1<decltype(cr_ca)>() << "\t" << type_name1<decltype(cr_ca)>() << endl;

在这里插入图片描述
可以看到对于引用类型可以完美的输出,而对于cv限定的变量类型也能很好的输出其类型,比如如下的volatile const类型变量:

  1. volatile const int value = 10;
  2. cout << type_name1<decltype(value)>() << "\t" << type_name1<decltype(value)>() << endl;

在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,170人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C++ 变量类型

    C++ 变量类型 变量其实只不过是程序可操作的存储区的名称。 在 C++ 中,有多种变量类型可用于存储不同种类的数据。 C++ 中每个变量都有指定的类型,类型决定了变

    相关 C 变量存储类型

    积木网络|C语言中的变量具有两种属性:一个是数据类型,一个是存储类型。根据变量所存放的数据的性质不同而分为各种数据类型;根据变量的存储方式不同而分为各种存储类型。变量的数据类型