【问题标题】:Comparing two type_info from typeid() operator比较来自 typeid() 运算符的两个 type_info
【发布时间】:2019-04-27 07:30:54
【问题描述】:

可以比较两个 typeid() 结果的结果吗? cppreference 有关于这个操作符的注释:

不保证相同的 std::type_info 实例将 由 typeid 表达式的所有求值引用 类型,尽管那些 type_info 对象的 std::type_info::hash_code 将是相同的,它们的 std::type_index 也是如此。

const std::type_info& ti1 = typeid(A);
const std::type_info& ti2 = typeid(A);

assert(&ti1 == &ti2); // not guaranteed
assert(ti1.hash_code() == ti2.hash_code()); // guaranteed
assert(std::type_index(ti1) == std::type_index(ti2)); // guaranteed

我的理解是返回是对 type_info 类型的静态 L 值的引用。这就是说 &ti1 == &ti2 对于相同的类型不能保证是相同的。相反,它说使用哈希码或 std::type_index 类。但是它没有提到是否直接比较类型:

ti1 == ti2; 

保证为真。我以前用过这个,文档是否暗示这是有保证的?

【问题讨论】:

  • 你以前直接比较过它们吗?他们的规范不包括operator==。如果您的目标是便携性,最好不要这样做。
  • @StoryTeller 哪个规范不包括operator==?
  • @StoryTeller 我可能会误解你,但肯定有operator ==
  • @Jodocus - 真的吗?我是否混淆了type_index 与难以忍受的before 成员合作的必要性?
  • @StoryTeller 我认为在检查类型标识时没有直接需要before

标签: c++ typeid


【解决方案1】:

std::type_info 是类类型,这意味着ti1 == ti2 表达式将触发重载的operator==。其行为由[type.info]/p2描述:

bool operator==(const type_info& rhs) const noexcept;

效果:将当前对象与rhs进行比较。

返回true 如果两个值描述相同的类型

【讨论】:

  • 是的。此外,p7 声明 hash_code() 应为 比较type_info 实例返回相同的值。所以如果不是operator ==,就无法保证hash_code()
【解决方案2】:

关于实现的一些信息可能很有趣:对于 g++/clang,type_info 以两个指针开头。第二个指向一个固定的字符串,就是name()返回的值。

** 请注意,此实现不是标准要求的,并且可能因同一编译器的不同目标而异。

首先检查type_info是否在同一个地址进行比较;如果是,它们是平等的;如果没有,接下来在两个“名称”字符串上调用 strcmp()。 strcmp 结果决定了.before() 方法的排序(以及扩展,type_index 的排序)。

通常,对于任何给定的类型,程序中只有一个 type_info。但是,当使用共享库时,最终可能会在共享库中使用一个,而在其他地方使用另一个。所以,比较地址并不足以检验两个type_info是否代表同一个类型,也不能用地址进行排序。 如果同一类型存在两个 type_info,它们的 name() 将返回等效的字符串,但这些字符串的地址不同,因为字符串常量和 type_info 是一起生成的。

.hash_code() 方法令人失望:它调用一个函数对name() 字符串逐个字符进行哈希处理。 g++ 版本调用strlen 来查找它的len,然后调用用于std::hash(std::string) 的相同函数。即使类型不是未知的,也会发生这种情况,例如typeid(std::complex<float>).hash_code()- 原则上,编译器可以在编译时计算结果。

在我的 x86_64 clang++-9.0 安装中,我看到了一个奇怪的结果 - hash_code() 返回与 name() 相同的内容,但转换为 size_t。这通常会起作用,但在程序中存在两个相同类型的 type_info 的情况下会失败。此外,它不是一个非常丰富的哈希,请考虑出现在 64 位地址空间内的值范围。我的安装可能会以某种方式获取错误的头文件,这就是结果,但它似乎可以正常工作。也许这是一个实际的缺陷,没有人使用 hash_code() 因为它太慢了......

我为RISC处理器尝试了另一个clang-9,它类似于g++的hash_code(),但不需要调用strlen。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多