相同的类型名称,但不是标准::is_same

Same typeid name but not std::is_same

本文关键字:标准 is same 类型      更新时间:2023-10-16

使用C++(gcc 4.8.3(我有2种类型(T1T2(,它们具有奇怪的性质,即typeid(T1).name()typeid(T2).name()是相同的,但是 std::is_same<T1, T2>::value false.

这怎么可能?我如何进一步调查以判断原因可能是什么?

忽略多态性,typeid()为您提供一个表示表达式静态类型的对象。但是,当涉及到表达式类型时,某些元素会被忽略。从 [expr]:

如果表达式最初具有"对T的引用"类型(8.3.2,8.5.3(,则该类型将调整为T 任何进一步的分析。[...]如果 prvalue 最初具有类型"cv T",其中 Tcv 不合格的非类、非数组类型,则类型 在进行任何进一步分析之前,将表达式调整为T

因此,任何仅在顶级简历资格或参考方面不同的类型都将产生相同的类型ID。例如,intconst intint& volatile const int&&等类型都给你相同的typeid()

基本上,你最初的思考过程是:

typeid(T) == typeid(U) <==> std::is_same<T, U>

但正确的等价是:

typeid(T) == typeid(U) <==> std::is_same<expr_type<T>, expr_type<U>>

哪里:

template <class T>
using expr_type = std::remove_cv_t<std::remove_reference_t<T>>;

typeid忽略所有 cv 限定符:

在所有情况下,cv-限定符都被typeid忽略(即typeid(T(==typeid(const T((

(参考资料(

这意味着typeid忽略所有引用&const(仅举几例(。

int i = 0;
const int&& j = 1;
if (typeid(i).hash_code() == typeid(j).hash_code()) //returns true
    std::cout << "typeid(int) == typeid(const int&&)";

请注意,要比较 2 typeid s,您必须使用 typeid(T).hash_code()std::type_index(typeid(T)) ,因为只有对于这 2 个函数才能保证 2 个相同的typeid s 是相同的。例如,比较引用并不能保证。

不能保证同一类型上 typeid 表达式的所有计算都会引用相同的 std::type_info 实例,尽管这些type_info对象的 std::type_info::hash_code 是相同的,它们的 std::type_index 也是如此。

(参考资料(


如@Yakk所述,您可以使用std::remove_referencestd::remove_cv来获得所需的行为。

std::remove_reference 删除 T 的所有引用,std::remove_cv删除所有constvolatile限定符。在将这些函数传递给 std::is_same 之前,您应该通过这些函数传递T,以便std::is_same仅比较 T1T2 的基础类型(如果有(。