【问题标题】:Same typeid name but not std::is_same相同的 typeid 名称但不是 std::is_same
【发布时间】:2016-04-12 15:27:33
【问题描述】:

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

怎么可能?我如何进一步调查以确定原因可能是什么?

【问题讨论】:

  • typeid 忽略顶级限定符。
  • ^^ 表示 const 和 &
  • @SergeyA 可能无法保证typeid 会给您相同 std::type_info 对象,但它保证所有@从 typeid(T) 返回的 987654330@ 对象对于相同的 T 比较相等。根据 C++14 18.7.1/3,如果两个操作数描述相同的类型,std::type_info::operator== 将返回 true
  • @SergeyA:我认为这是对标准的恶意解读。 [type.info]/1 说“适合比较两种类型是否相等”,我认为这几乎可以排除愚蠢的事情,比如总是返回true
  • 为什么需要hash_code 进行比较?似乎更合理的是引入hash_code 以允许将 typeid 粘贴到无序容器中。另外,不要将 name 与 typeid 结果的值混淆。没有人声称 names 具有所需的属性(您肯定不想散列名称)。

标签: c++ c++11


【解决方案1】:

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

如果表达式最初的类型为“引用T”(8.3.2, 8.5.3),则该类型在之前调整为T 任何进一步的分析。 [...] 如果纯右值最初的类型为“cv T”,其中 Tcv 非限定的非类、非数组类型, 的类型 在进行任何进一步分析之前,将表达式调整为 T

因此,任何仅在顶级 cv 限定或引用方面不同的类型都将产生相同的 typeid。例如,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>>;

【讨论】:

    【解决方案2】:

    typeid 忽略所有 cv 限定符:

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

    (ref)

    这意味着typeid 会忽略所有引用&amp;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 个typeids,您必须使用typeid(T).hash_code()std::type_index(typeid(T)),因为只有这两个函数才能保证两个相同的typeids 相同。例如,比较参考没有这种保证。

    虽然那些 type_info 对象的 std::type_info::hash_code 会是相同的,但不能保证相同类型的 typeid 表达式的所有计算都会引用相同的 std::type_info 实例他们的 std::type_index。

    (ref)


    正如@Yakk 所提到的,您可以使用std::remove_referencestd::remove_cv 来获得您想要的行为。

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

    【讨论】:

    • 他们的operator == 也保证评估true 相同类型的描述符。所以你不能可靠地比较&amp;typeid(T) == &amp;typeid(T),但你可以比较typeid(T) == typeid(T)并可靠地得到true
    • 提及 remove_referenceremove_cv 可能有助于 OP 解决他们的根本问题(而不仅仅是他们的标题问题)。
    猜你喜欢
    • 1970-01-01
    • 2022-10-16
    • 2021-05-29
    • 1970-01-01
    • 2011-06-27
    • 2016-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多