std::type_index能用于多态对象运行时类型识别,因其封装typeid(*ptr)返回的动态类型std::type_info,RTTI开启时自动获取实际派生类类型;它语义等价、跨编译单元可靠,且标准库已特化hash支持unordered_map。

直接用 std::type_index 作多态集合的键是安全且高效的,但必须确保所有键来自 typeid 表达式、RTTI 开启、类型修饰符一致——否则查不到、插不进、行为未定义。
为什么 std::type_index 能用于多态对象的运行时类型识别
std::type_index 封装的是 std::type_info 的语义等价性,而 typeid(*ptr) 在多态对象上会返回**动态类型**的 std::type_info(前提是 RTTI 开启)。这意味着:std::type_index{typeid(*base_ptr)} 给出的不是 Base,而是实际派生类(如 DerivedA)的类型索引。
常见错误现象:typeid(ptr) 返回的是指针类型(Base*),不是所指对象类型;写成 typeid(Base*) == typeid(DerivedA*) 永远为 false,且毫无意义。
- 正确做法:对多态指针,必须解引用或传引用:
typeid(*ptr)或typeid(obj_ref) - 非多态类型(无虚函数)上
typeid只返回静态类型,无法实现动态识别 -
std::type_index的==比较是语义等价,不是地址比较,因此跨编译单元也可靠
std::unordered_map<:type_index t> 插入与查找的典型写法
标准库从 C++11 起已特化 std::hash<:type_index></:type_index>,所以 std::unordered_map<:type_index t></:type_index> 可直接使用,无需自定义哈希器——但要注意构造方式。
立即学习“C++免费学习笔记(深入)”;
常见错误现象:std::type_index(typeid(T)) 可能被解析为函数声明(most vexing parse),尤其在模板上下文中;decltype(typeid(T)) 是 const std::type_info&,不可拷贝,不能作键。
- 必须显式用花括号初始化:
std::type_index{typeid(ConcreteX)} - 注册和查询必须用同一“类型形态”:注册
typeid(ConcreteX),就不能用typeid(const ConcreteX&)去查 - 工厂示例中,
factory[std::type_index{typeid(ConcreteX)}] = []{ return std::make_unique<concretex>(); };</concretex>是安全模式
cv 限定符和引用修饰导致查不到的坑
std::type_index 对 const、volatile、引用、指针完全敏感。这是由 typeid 语义决定的,std::type_index 忠实反映它。
常见错误现象:注册了 std::type_index{typeid(MyClass)},却用 std::type_index{typeid(const MyClass)} 或 std::type_index{typeid(MyClass&)} 查找,结果 find() 返回 end()。
- 统一约定:注册和查询都用“裸类型值”(
MyClass),避免带const、&、* - 对指针类型,
typeid(T*)和typeid(T)是两个完全不同的键,别混用 - 若需支持
const版本,得单独注册:std::type_index{typeid(const MyClass)}
RTTI 关闭时的崩溃与编译检查
一旦禁用 RTTI(如 GCC/Clang 的 -fno-rtti),typeid 对多态类型的求值行为是未定义的:可能编译失败、运行时抛 std::bad_typeid、或静默返回错误类型。
常见错误现象:代码在本地调试正常,上线后因构建配置关闭 RTTI 导致 typeid(*ptr) 崩溃;或 std::type_index{typeid(T)} 构造失败。
- 必须确认构建系统开启 RTTI(默认开启,但嵌入式/性能敏感项目常显式关闭)
-
std::type_index本身不触发新 RTTI,但它依赖typeid的输出,所以 RTTI 是硬前提 - 不能用于只有前置声明的类(
class X;),必须有完整定义
最易忽略的一点:std::type_index::hash_code() 的返回值只保证单次进程内稳定,不同运行、不同平台、不同编译器之间都不一致——别拿它存数据库、发网络、做持久化 ID。


















