直接用 std::type_index 作异构容器键可行但易踩坑:①必须用花括号初始化 std::type_index{typeid(T)},禁用 &typeid(T) 防悬垂指针;②注册与查询类型修饰符须完全一致;③多态对象需解引用 typeid(*ptr);④启用 RTTI 并包含 和 ;⑤与 std::any 配合时避免存储 const std::type_info& 地址。

直接用 std::type_index 作异构容器键是可行的,但只要踩中生命周期、类型修饰符、哈希器这三类坑中的任意一个,就会查不到、崩溃或跨编译单元行为不一致——这不是库的问题,而是对 std::type_index 和 typeid 语义理解偏差导致的。
必须用花括号初始化 std::type_index{typeid(T)},禁用 &typeid(T)
typeid 表达式返回的是临时 const std::type_info&,对其取地址(如 &typeid(MyClass))会立即生成悬垂指针。后续任何比较、哈希或解引用都触发未定义行为。
- 错误写法:
factory[&typeid(MyClass)] = handler;、std::type_index(typeid(MyClass))(可能被解析为函数声明) - 正确写法:
std::type_index{typeid(MyClass)}、std::type_index{typeid(*ptr)}(多态对象必须解引用) - 对模板参数退修饰:
std::type_index{typeid(std::remove_cvref_t<t>{})}</t>,避免T = const MyClass&导致键含冗余修饰
注册与查询的类型修饰符必须完全一致
std::type_index 对 const、&、*、volatile 完全敏感。哪怕只是声明差异,键就不同:例如 std::type_index{typeid(int)} ≠ std::type_index{typeid(const int)},也 ≠ std::type_index{typeid(int&)}。
- 注册工厂时建议统一用值类型:
factory[std::type_index{typeid(MyClass)}] = []{ return std::make_unique<myclass>(); };</myclass> - 查询时若接收
const T& x,不能直接用typeid(x),应改用std::type_index{typeid(std::remove_cvref_t<decltype>{})}</decltype> - 对多态指针,必须用
typeid(*ptr);typeid(ptr)返回的是指针类型(如Base*),不是实际派生类
std::unordered_map<:type_index t></:type_index> 编译失败?优先验证哈希器和 RTTI
虽然 C++11 标准要求特化 std::hash<:type_index></:type_index>,但旧编译器(如 GCC 4.8、MSVC 2013)、禁用 RTTI(-fno-rtti)或遗漏头文件都会导致编译失败,典型报错:error: no match for call to ‘std::hash<:type_index>()’</:type_index>。
立即学习“C++免费学习笔记(深入)”;
- 确认已启用 RTTI:GCC/Clang 检查是否含
-frtti(默认开启),MSVC 确认/GR已设 - 头文件缺一不可:
#include <typeindex></typeindex>和#include <typeinfo></typeinfo> - 验证哈希器可用:
static_assert(std::is_default_constructible_v<:hash>>);</:hash>,失败则显式传入:std::unordered_map<:type_index t std::hash>></:type_index> - 更稳妥的选择是直接用
std::map:它只依赖operator,而 <code>std::type_index已完整支持
与 std::any 配合时最容易忽略的生命周期陷阱
std::any::type() 返回的是 const std::type_info&,其生命周期绑定于该 std::any 对象。若将其地址存入容器或跨作用域使用,极易悬垂。
- 错误写法:
auto& ti = a.type(); map[&ti] = value;——ti是临时引用 - 正确写法:
map[std::type_index{a.type()}] = value;——std::type_index构造后独立持有指针 - 注意:
std::type_index::hash_code()值只在单次运行内稳定,不可用于日志、持久化或跨进程比对;唯一可靠的判断永远是==比较


















