比较来自typeid()运算符的两个type_info

时间:2018-11-25 13:12:57

标签: c++ typeid

可以比较两个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; 

保证是正确的。我以前用过,文档是否暗含了保证?

2 个答案:

答案 0 :(得分:5)

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

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

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

     

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

答案 1 :(得分:0)

一些有关实现的信息可能是令人感兴趣的:对于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。