std::type_index可直接作map键,因它可拷贝、重载比较与哈希,而std::type_info不可;错误用&typeid(T)致悬垂指针,须用std::type_index{typeid(T)};跨动态库时hash_code()不一致。

std::type_index 可以直接用作 std::map 或 std::unordered_map 的键,但必须显式构造、统一类型修饰、开启 RTTI,否则查不到、崩溃或编译失败。
为什么 std::map<:type_index t></:type_index> 能编译通过,而 std::map<const std::type_info t></const> 不行
因为 std::type_info 禁止拷贝、无默认构造、不提供 operator<,连声明 std::map<const std::type_info&, T> 都会触发 “use of deleted function” 编译错误;std::type_index 是专为容器设计的包装:它可拷贝、可移动、重载了 ==/!=、提供 hash_code(),且能隐式转换自 const std::type_info&。
常见错误写法:factory[&typeid(MyClass)] = ... —— typeid(MyClass) 是临时对象,取地址后得到悬垂指针,后续访问未定义。
正确做法始终是:std::type_index{typeid(MyClass)},让 type_index 内部保存并管理 const std::type_info* 生命周期。
立即学习“C++免费学习笔记(深入)”;
std::unordered_map<:type_index t></:type_index> 编译失败?检查这三件事
虽然 C++11 标准要求特化 std::hash<:type_index></:type_index>,但实际编译失败通常由以下原因导致:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 编译器标准未设为 C++11 或更高(如 GCC 用
-std=c++98) - RTTI 被显式关闭(如
-fno-rtti),导致typeid行为未定义,连带std::type_index构造失败 - 头文件遗漏:
#include <typeindex>和#include <typeinfo>都不可少
验证方式:static_assert(std::is_default_constructible_v<std::hash<std::type_index>>);,不通过就得手动传哈希器,例如:std::unordered_map<std::type_index, T, std::hash<std::type_index>>。
注册和查询时 std::type_index 对不上?大概率是 cv 限定符或引用不一致
std::type_index 对 const、volatile、引用、指针完全敏感。哪怕只是声明差异,键就不同:
-
std::type_index{typeid(int)}≠std::type_index{typeid(const int)} -
std::type_index{typeid(MyClass)}≠std::type_index{typeid(const MyClass&)} -
std::type_index{typeid(ptr)}得到的是指针类型(如MyClass*),不是所指对象类型;应改用std::type_index{typeid(*ptr)}
统一约定建议:工厂/策略注册与查询一律使用“值类型”,即 std::type_index{typeid(T)}(T 是非引用、非 const 的完整类型),模板函数中慎用 decltype(x)——若 x 是 const MyClass&,键就带 const& 修饰,和注册时对不上。
和 std::any 搭配做类型擦除容器时的关键约束
用 std::type_index 管理 std::any 的类型映射表很常见,但要注意:
-
std::any::type()返回的是const std::type_info&,必须立刻转成std::type_index再查表,不能缓存该引用(生命周期短于any) - 注册键必须与
std::any::type()返回的类型完全一致:存的是std::any{42},其type()是typeid(int),不是typeid(long)或typeid(unsigned) - 前置声明类(
class X;)后直接typeid(X)是非法的,必须有完整定义
最易被忽略的一点:同一类型在不同动态库中生成的 std::type_index 哈希值可能不一致,hash_code() 仅保证单次进程内稳定,跨 DLL/so 边界不可靠。

















