可行但需谨慎:std::type_index{typeid(T)}在模板中非法,应改用std::type_index{typeid(T{})}或std::type_index{typeid(std::declval())};注册与查询类型修饰符须严格一致,cv限定、引用、指针均影响键唯一性。

直接用 std::type_index 作异构容器(如 std::map 或 std::unordered_map)的键是可行的,但查不到、崩溃、跨编译单元不一致——八成不是代码逻辑问题,而是 std::type_index 构造或使用方式踩了坑。
std::type_index{typeid(T)} 必须作用于具体表达式,不能写 typeid(T)
模板中直接写 typeid(T) 是非法的:T 是未实例化的类型名,不是表达式,某些编译器会静默接受但行为未定义;更常见的是编译失败或生成错误的 std::type_info 实例。
- 错误写法:
template<typename t> void reg() { factory[std::type_index{typeid(T)}] = ...; }</typename> - 正确写法(推荐):
std::type_index{typeid(T{})}(要求 T 可默认构造) - 更通用写法:
std::type_index{typeid(std::declval<t>())}</t>(需#include <utility></utility>,且 T 满足可假想构造) - 最稳妥写法(非模板上下文):
std::type_index{typeid(ConcreteA)},明确、无歧义
注册与查询的类型修饰符必须严格一致
std::type_index 完全继承 typeid 的语义:int、const int、int&、int* 全是不同键。哪怕变量声明为 const int x = 42;,std::type_index{typeid(x)} 和 std::type_index{typeid(int)} 也不相等。
- 工厂注册时,统一用裸值类型:
factory[std::type_index{typeid(MyClass)}] = []{ return std::make_unique<myclass>(); };</myclass> - 对引用参数
const T& obj,查类型应取模板参数:std::type_index{typeid(T)},而非typeid(obj) - 对多态指针
Base* ptr,必须解引用才能获得实际类型:std::type_index{typeid(*ptr)};typeid(ptr)返回的是Base*类型,不是派生类 - 涉及 cv 限定时,显式退修饰:
std::type_index{typeid(std::remove_cv_t<:remove_reference_t>>)}</:remove_reference_t>
std::unordered_map<:type_index t> 编译失败?先验证哈希器是否就绪
标准从 C++11 起已特化 std::hash<:type_index></:type_index>,但 GCC 4.8、MSVC 2013 等旧环境,或项目禁用 RTTI(-fno-rtti)时,std::unordered_map<:type_index t></:type_index> 仍可能报 “no matching function for call to ‘hash’”。
立即学习“C++免费学习笔记(深入)”;
- 验证方式:
static_assert(std::is_default_constructible_v<:hash>>);</:hash>,失败即需干预 - 修复方式一(推荐):改用
std::map<:type_index t></:type_index>,无需哈希器,operator 已内置,性能差异在绝大多数场景下可忽略 - 修复方式二:显式传入标准哈希器:
std::unordered_map<:type_index t std::hash>></:type_index> - 切勿手写哈希器调
ti.hash_code()——它本就是std::hash特化的底层依据,重复封装无意义且易错
RTTI 关闭会导致 std::type_index 静默失效
关掉 RTTI 后,typeid 行为未定义,std::type_index 构造可能返回无效指针,find() 总是失败,但编译和运行都不会报错——这是最隐蔽的问题来源。
- GCC/Clang 默认开启 RTTI,但若构建脚本含
-fno-rtti,必须去掉 - MSVC 需确认未启用
/GR-;启用时应为/GR(默认) - 头文件不可少:
#include <typeindex></typeindex>和#include <typeinfo></typeinfo>都要显式包含 -
hash_code()值只保证单次进程内稳定,绝不可用于日志、数据库或网络传输——它不是类型 ID,只是哈希桶索引


















