【发布时间】:2012-01-03 10:54:34
【问题描述】:
这里有一些CRTP based template code,我曾经尝试解决这个问题:Requiring overridden virtual functions to call base implementations。我会在这里发布代码,但是这些行很长,并且在 codepad.org 上更容易阅读(如果需要,我会在这里发布)。当然,它很丑陋,而且有些人为,尽管它确实有效。但我一开始并没有意识到,虽然它可以在 MSVC++ 和 GCC 上编译,但某些模板类型并没有真正定义。我要质疑的部分是顶部TBase::OnEvent 函数中的几个长内部if( typeid( Derived(N) ) != typeid( Derived(N-1))(符号表示法)。
你不能typdef这些类型,这将是一个编译错误——没有足够的派生类来定义这么长的...::TDerived::...链类型,所以你会正确地得到编译错误@987654328 @。然而编译器通过typeid 吃掉了它们。当我检查调试器 MSVC++ 编译器输出(带有完整的符号信息)时,似乎所有那些不应该真正导致任何类的长 ...::TDerived::... 在 typeid 中被编译器解析为类链中的最后一个 TDerived04 .并且为类链中的最后一个类提取 RTTI,与我有多少 ...::TDerived::... 无关。
考虑到 MSVC++ 和 GCC 都是这样做的(尽管我只能通过 codepad.org 访问 GCC),接下来我的问题是:它是否以某种方式定义了 typeid 的行为?那么为什么那些长的...::TDerived::... 中的typedef 不能解析为TDerived04?
编辑:我的意思是,我很高兴typedef 不能解析为TDerived04,这对于使用typedef 的任何人来说都是一场灾难,但是为什么typeid 和typedef 之间存在这种不一致呢?
编辑:GCC 接受 TDerived04::TDerived04::TDerived04::TDerived04 lD4; 变量声明。最后的类型就是TDerived04。是否有折叠范围解析的规则?显然,MSVC++ 和 GCC 在typeid 中似乎都在做同样的事情,但是 MSVC++ 与 GCC 不同,它无法处理其他情况 - 它会产生编译错误,需要构造函数的参数。
【问题讨论】:
-
快速浏览一下代码后,您似乎正在尝试“重新实现”虚函数。还是我错过了什么?
-
@elmo 好吧,CRTP 允许实现某种“编译器时解析的虚拟机制”。我确实在回答与虚拟功能相关的问题。具体来说,在 base-derived00-derived01...-derivedLast 链中实现对中间类中所有函数的调用,而不在任何这些类中指定实际函数调用(如果感兴趣,请参阅原始问题)......但这不是这里的问题,这只是框架。我想知道
typeid的行为。 -
this 能解决您的问题吗?一般来说,我会考虑仅将 typeid 用于打印以进行调试。
-
@elmo 这是对原始问题的一个非常优雅的解决方案。我建议你把它贴在那里(见我的问题帖子中的链接)。另外,如果您将此代码+有关名称解析的评论结合到一个答案中,我会接受它。 MSalters 的回答只是指向方向,因为没有实际的构造函数解析进化(注意我的
typeid中的typename关键字)。 -
在这里和那里作为答案发布。如果您发现其中缺少任何内容,请告诉我。
标签: c++ templates compiler-construction crtp typeid