std::type_index可安全用作map键,因其可拷贝、支持比较与哈希,而std::type_info&不可用;需开启rtti,注意类型修饰符敏感性、hash_code()非持久化及完整类型要求。

std::type_index 可以安全用作多态集合的键,但必须配合 typeid 表达式显式构造,且对 cv 限定符、引用、指针类型极度敏感——稍有不一致就查不到。
为什么不能直接用 typeid(T) 当 map 键
因为 typeid 返回的是 const std::type_info&,它不可拷贝、不可构造、无默认比较语义,也不能存进标准容器。写 std::map<decltype int></decltype> 会编译失败;哪怕绕过(比如存指针),std::type_info::operator== 在旧标准下行为未定义,且无法哈希。
std::type_index 就是为解决这个问题设计的:它可拷贝、可移动、重载了 operator== 和 operator,还提供 <code>hash_code(),能隐式转换自 const std::type_info&。
- 常见错误:写
std::type_index(typeid(int))—— 某些编译器会触发“最令人烦恼的解析”(most vexing parse),变成函数声明 - 正确写法必须加花括号:
std::type_index{typeid(int)} - 临时
typeid结果生命周期极短,裸取地址会导致悬垂指针;std::type_index内部只存 const 指针,但封装后语义稳定
std::unordered_map<:type_index t></:type_index> 要手动提供哈希器吗
不需要——C++11 起标准已特化 std::hash<:type_index></:type_index>,主流编译器(GCC/Clang/MSVC)都支持直接使用。
但要注意:std::type_index::hash_code() 是实现定义的,同一程序多次运行可能返回不同值,不能用于持久化或网络传输。
- 别把
hash_code()当作类型唯一 ID;它只适合单次进程内哈希查找 - 注册时用
std::type_index{typeid(ConcreteA)},查询时也必须用完全一致的表达式,比如不能用typeid(const ConcreteA&) - 对多态对象,要识别动态类型,必须传 *ptr 或引用,而不是指针本身:
typeid(*p)✅,typeid(p)❌(后者返回指针类型)
cv 限定符和引用类型导致查不到的典型场景
std::type_index 忠实反映 typeid 的语义:它对 const/volatile/引用修饰符敏感。这意味着 std::type_index{typeid(int)} 和 std::type_index{typeid(const int)} 不相等,哪怕你传的是 const int x = 42;。
- 注册策略类时用了
std::type_index{typeid(MyHandler)},但调用时传了std::type_index{typeid(const MyHandler&)}→ 查不到 - 工厂注册统一用值类型(如
MyClass),所有查询也必须用值类型,避免混用MyClass*、const MyClass& - 模板函数里获取
std::type_index,推荐写std::type_index{typeid(T{})},而非typeid(T)(后者在某些上下文中未定义)
RTTI 必须开启,且类型需有完整定义
typeid 行为在 RTTI 关闭时未定义,GCC/Clang 默认开启,但嵌入式或性能敏感项目常加 -fno-rtti,此时 typeid 会编译失败或运行崩溃。
std::type_index 也依赖 RTTI,且只能用于有完整定义的类型(不能用于仅前置声明的类)。
- 检查是否开启 RTTI:GCC/Clang 看是否有
-frtti(默认);MSVC 看项目属性 → C/C++ → 语言 → 启用运行时类型信息 - 前置声明类(如
class Foo;)不能用于typeid(Foo),否则编译报错 “invalid use of incomplete type” - 即使开启 RTTI,对纯右值(如
typeid(42 + 1))也能工作,但对多态对象空指针解引用仍抛std::bad_typeid
真正容易被忽略的不是语法,而是类型修饰的一致性——注册和查询两端的 typeid 表达式必须在 cv、引用、指针层级上完全匹配,差一个 const 或 & 就失效。这不是 bug,是 typeid 语义的必然结果。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











