std::type_info::name() 的实际目的是什么?

What is the actual purpose of std::type_info::name()?

今天有个同事来问我标题中的问题
他目前正在尝试减少代码库的二进制文件占用空间,该代码库也用于小型目标(如 Cortex M3 等)。显然他们已经决定在打开 RTTI(实际上是 GCC)的情况下进行编译,以支持正确的异常处理。

嗯,他的主要抱怨是为什么实际上根本需要 std::type_info::name() 来支持 RTTI,并问我是否知道一种方法来抑制生成支持此所需的字符串文字,或者在至少要缩短它们。

std::type_info::name

const char* name() const; Returns an implementation defined null-terminated character string containing the name of the type. No guarantees are given, in particular, the returned string can be identical for several types and change between invocations of the same program.

A,-但是特定于编译器-,实现例如dynamic_cast<> 运算符不会使用此信息,而是使用类似 hash-tag 的信息来确定类型(类似于具有异常处理的 catch() 块)。
我认为

的当前标准定义清楚地表达了后者
  1. std::type_info::hash_code
  2. std::type_index

我不得不同意,除了用于调试(日志记录)目的之外,我也没有真正看到使用 std::type_info::name() 的意义。我不是 100% 确定异常处理在没有 RTTI 的情况下也能在当前版本的 GCC 中工作(我认为他们使用的是 4.9.1),所以我犹豫是否建议简单地关闭 RTTI。
此外,他们的代码库中使用了 dynamic_casts<>,但对于这些,我只是建议不要使用它,而建议使用 static_cast(他们实际上没有插件之类的东西,或者需要用于断言以外的运行时类型检测)。


问题:

Sub-Questions(更具体):


相关位:Strip unused runtime functions which bloat executable (GCC)

隔离这个位:

  • 关键是,如果他们关闭 RTTI,GCC 中的异常处理是否仍能正常工作?

answer是:

-fno-rtti

Disable generation of information about every class with virtual functions for use by the C++ runtime type identification features (dynamic_cast and typeid). If you don't use those parts of the language, you can save some space by using this flag. Note that exception handling uses the same information, but it will generate it as needed. The dynamic_cast operator can still be used for casts that do not require runtime type information, i.e. casts to void * or to unambiguous base classes.

Are there real life, production code level use cases for std::type_info::name() other than logging?

Itanium ABI describes operator== std::type_info 对象如何通过测试从 std::type_info::name() 返回的字符串的指针相等性来轻松实现。

在非平面地址 space 中,同一类型可能有多个 type_info 对象(例如,因为动态库已加载 RTLD_LOCAL ) operator== 的实现可能需要使用 strcmp 来确定两个类型是否相同。

所以name()函数用来判断两个type_info对象是否引用同一个类型。对于实际用例的示例,通常在标准库中至少有两个地方使用,在 std::function<F>::target<T>()std::get_deleter<D>(const std::shared_ptr<T>&).

如果你不使用 RTTI 那么所有这些都是无关紧要的,因为你不会有任何 type_info 对象(因此在 libstdc++ 中 function::targetget_deleter 函数可以不能使用)。

我认为 GCC 的异常处理代码使用 type_info 对象本身的地址,而不是 name() 返回的字符串的地址,所以如果你使用异常但没有 RTTI name() 不需要字符串。