如何获取C++中变量/表达式的类型
主要有三种方式:
- 使用 C++ 库自带的 typeid 函数;
- 使用 boost 库中 type_id_with_cvr 函数(末尾的 cvr 代表const, variable, reference);
- 自定义模板函数 type_name();
方式一:
typeid 会把获取到的类型信息保存到一个 type_info 类型的对象里面,并返回该对象的常引用;当需要具体的类型信息时,可以通过成员函数来提取。
不像 Java、C# 等动态性较强的语言,C++ 能获取到的类型信息非常有限,也没有统一的标准,如同“鸡肋”一般,大部分情况下我们只是使用重载过的“==”运算符来判断两个类型是否相同。
#include <typeinfo> #include <iostream> int main() { int a = 100; const int b = 101; int& lref = a; int&& rref = std::move(a); std::cout << "int a: type is " << typeid(a).name() << std::endl; std::cout << "const int b: type is " << typeid(b).name() << std::endl; std::cout << "int& lref: type is " << typeid(lref).name() << std::endl; std::cout << "int&& rref: type is " << typeid(rref).name() << std::endl; return 0; }
可以发现:使用 typeid() 打印出来的类型不直观,并且它不支持引用类型的变量,也不能区分const变量。
方式二:
使用 boost 库中 type_id_with_cvr 函数(末尾的cvr代表const, variable, reference),这个方法打印出来的结果就比较优雅了(准确)
但需要下载 Boost 库,并编译安装,才能使用。
#include <iostream> #include <boost/type_index.hpp> int main() { int a = 100; const int b = 101; int& lref = a; int&& rref = std::move(a); std::cout << "int a: type is " << boost::typeindex::type_id_with_cvr<decltype(a)>().pretty_name() << std::endl; std::cout << "const int b: type is " << boost::typeindex::type_id_with_cvr<decltype(b)>().pretty_name() << std::endl; std::cout << "int& lref: type is " << boost::typeindex::type_id_with_cvr<decltype(lref)>().pretty_name() << std::endl; std::cout << "int&& rref: type is " << boost::typeindex::type_id_with_cvr<decltype(rref)>().pretty_name() << std::endl; return 0; }
输出结果:
int a: type is int const int b: type is int const int& lref: type is int& int&& rref: type is int&&
方式二:
定义了一个模板函数 type_name(),可以对传入的模板类型 T 进行类型判断,结合指针、左值/右值引用、常类型,准确得出变量的类型。在调用该函数时使用了decltype
关键字,传入待确定的变量,然后输出变量类型。
#include <type_traits> #include <typeinfo> #include <memory> #include <string> #include <cstdlib> #include <iostream> #ifndef _MSC_VER #include <cxxabi.h> #endif using namespace std; template <class T> string type_name() { typedef typename remove_reference<T>::type TR; unique_ptr<char, void (*)(void *)> own( #ifndef _MSC_VER abi::__cxa_demangle(typeid(TR).name(), nullptr, nullptr, nullptr), #else nullptr, #endif free); string r = own != nullptr ? own.get() : typeid(TR).name(); if (is_const<TR>::value) r += " const"; if (is_volatile<TR>::value) r += " volatile"; if (is_lvalue_reference<T>::value) r += "&"; else if (is_rvalue_reference<T>::value) r += "&&"; return r; } int main() {
int a = 100;
const int b = 101;
int& lref = a;
int&& rref = std::move(a);
cout << "int a: type is " << type_name<decltype(a)>() << endl;
cout << "const int b: type is " << type_name<decltype(b)>() << endl;
cout << "int& lref: type is " << type_name<decltype(lref)>() << endl;
cout << "int&& rref: type is " << type_name<decltype(rref)>() << endl;
}
结果如下:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?