std::type_index不能直接用于指针的多态识别,因typeid(ptr)返回指针类型而非所指对象类型;必须用typeid(*ptr)解引用获取动态类型,且需确保RTTI开启、目标类型含虚函数、非空指针。

std::type_index 可以安全用作多态对象集合的类型键,但必须配合 typeid 表达式构造,且不能直接用于指针——要传 *ptr 或引用才能获得动态类型。
为什么 typeid(ptr) 不能用于多态识别
对指针本身调用 typeid 返回的是指针类型(如 Base*),不是它指向的对象类型。哪怕 ptr 实际指向 Derived,typeid(ptr) 永远只认出 Base*。
- 正确做法是解引用:用
typeid(*ptr)或typeid(static_cast<const base>(*ptr))</const> - 若
ptr为空,typeid(*ptr)会抛出std::bad_typeid,需提前判空 - 目标类型必须含虚函数(即多态类型),否则
typeid(*ptr)返回静态类型,失去多态意义
std::map<:type_index t></:type_index> 注册时的构造陷阱
常见错误是写成 std::type_index(typeid(T)),这在某些编译器下会被解析为函数声明(most vexing parse),导致编译失败或行为异常。
- 必须用花括号初始化:
std::type_index{typeid(Concrete)} - 不能写
decltype(typeid(T))——std::type_info不可拷贝,该类型无法实例化容器 - 模板内注册需注意:若
T是模板参数,应写std::type_index{typeid(T{})}或std::type_index{typeid(typename std::decay_t<t>{})}</t>,避免未定义行为
std::unordered_map<:type_index t></:type_index> 编译失败怎么办
标准库未为 std::type_index 特化 std::hash,所以直接声明 std::unordered_map<:type_index t></:type_index> 会报错 “no match for call to ‘hash<:type_index>’”。
立即学习“C++免费学习笔记(深入)”;
- 解决方法:手动提供哈希器,例如
std::unordered_map<:type_index t std::hash>></:type_index>——但注意:C++20 起才保证std::hash<:type_index></:type_index>存在;C++17 及更早需自行定义 - 简易自定义哈希器示例:
struct type_index_hash {<br> size_t operator()(const std::type_index& ti) const noexcept {<br> return ti.hash_code();<br> }<br>};<br>// 使用:<br>std::unordered_map<std::type_index, T, type_index_hash> - 别用
typeid(T).hash_code()直接当哈希值——它不跨进程/跨次运行稳定,仅适合单次运行内比较
cv 限定符和引用敏感性带来的坑
std::type_index{typeid(int)} 和 std::type_index{typeid(const int)} 是两个不同键,即使你本意只是区分“整数类型”。
- 注册和查找必须严格一致:若存的是
typeid(const int),就不能用typeid(int)去查 - 对引用同理:
typeid(int&)≠typeid(int);多态场景下推荐统一用typeid(*ptr)(返回左值引用,但typeid忽略引用限定符) - 若需忽略 cv 限定,可用
std::remove_cv_t包一层:std::type_index{typeid(std::remove_cv_t<decltype>)}</decltype>
真正容易被忽略的是 RTTI 开关——如果项目用了 -fno-rtti(常见于嵌入式或性能关键路径),所有 typeid 表达式都会失效,std::type_index 就完全不可用。这不是语法问题,而是链接期或运行期崩溃的根源。务必确认构建配置中 RTTI 已启用。


















