Mag*_*gix 5 c++ gcc rtti c++17
我有以下一段代码:
template<typename T>
class genericHandler{public: using evt_t = T;};
template<typename T>
class specialHandler : public genericHandler<T> { /* more stuff */ };
int main(int argc, char *argv[]) {
std::any any_var = specialHandler<int>{};
auto f = [&any_var](auto evtHandler) {
using EventType = typename std::remove_reference<decltype(evtHandler)>::type ::evt_t;
if(any_var.type() == typeid(EventType)) { std::cout << "yes" << std::endl; } else { std::cout << "no" << std::endl; }
};
auto h = specialHandler<int>{ };
f(h);
}
Run Code Online (Sandbox Code Playgroud)
调用时,evtHandler是非多态派生类型specialHandler。根据cppreference,我们有:
当应用于多态类型的表达式时,typeid 表达式的计算可能涉及运行时开销(虚拟表查找),否则 typeid 表达式在编译时解析。
当我用 gcc and 编译时-fno-rtti,我收到以下错误消息:
不能将“typeid”与“-fno-rtti”一起使用
RTTI 是运行时类型信息,在编译时可以推导出的非多态 typeid 的情况下应该不需要。我错过了什么 ?
你在问两个问题。
RTTI是运行时类型信息,在非多态typeid的情况下不应该需要它...
但这是编译器开关,而不是语言功能,因此您应该检查编译器文档:
-fno-rtti
禁止生成有关每个具有虚函数的类的信息,以供 C++ 运行时类型识别功能(
dynamic_cast和typeid)使用。如果您不使用该语言的这些部分,则可以使用此标志节省一些空间。请注意,异常处理使用相同的信息,但它将根据需要生成它。该dynamic_cast运算符仍可用于不需要运行时类型信息的转换,即转换为 void * 或明确的基类。
(我的重点)。
因此该开关禁用整个 typeinfo 系统以节省空间。如果您愿意typeinfo(或者您想使用使用 的标准库工具typeinfo),则不要typeinfo使用编译器选项显式禁用。
...可以在编译时推导的非多态 typeid
编辑,正如韦克利先生指出的那样,问题在于您typeid在自己的代码中明确使用了。
虽然std::any可能能够在没有 RTTI 的情况下从顶级对象中删除存储的类型,但这取决于实现,并且如果不使用您告诉 GCC 不要生成的/ ,它绝对无法实现。std::any::type()typeidtypeinfo
哦,我忘了
我错过了什么 ?
是的,要问你的实际问题,那就是
我正在删除它,因为我需要解决循环模板依赖性,遗憾的是我不能在这里“简单地删除它”。我有没有不使用 RTTI 的替代方案
当然,类型擦除不依赖于 RTTI。
只有自动类型擦除依赖于 RTTI,并且如上所述,并非全部依赖于 RTTI。您可以避免std::any::type()或手动编写自己的可区分联合 - 您需要枚举您的类型,但只有枚举本身需要对 DU 的所有用户可见。