【问题标题】:Template mutual dependence模板相互依赖
【发布时间】:2011-01-25 22:44:49
【问题描述】:

模板 结构 A{ typedef 浮点型; typedef typename tB::btype typeB; }; 模板 结构 B{ typedef 浮动 btype; typedef typename tA::atype typeA; };

struct MyB;
struct MyA: public A<MyB>{};
struct MyB: public B<MyA>{};

int main(int argc, char *argv[])
{
}

无法编译,因为 “main.cpp:6: error: 无效使用不完整类型‘struct MyB’”。

基本上编译器无法解决循环,因为定义 A 的定义取决于 B 的定义,反之亦然。 有没有办法解决这个问题? 谢谢,

【问题讨论】:

  • MyB 的结构在哪里定义?
  • 可以做的是制作MyAMyB模板:template&lt;typename&gt; struct MyBT; template&lt;typename T&gt; struct MyAT : public A&lt; MyBT&lt;T&gt; &gt; { }; template&lt;typename T&gt; struct MyBT : B&lt; MyAT&lt;T&gt; &gt; { }; typedef MyAT&lt;void&gt; MyA; typedef MyBT&lt;void&gt; MyB;。但是这个解决方案很丑:)
  • 可悲的是,看起来我上面提出的代码在当前的 C++ 中格式不正确。但是,open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#287 有一个问题报告似乎使这个格式正确。虽然提议的措辞让我头疼:)

标签: c++ templates instantiation


【解决方案1】:

这无法直接解决。昨天发布了一个非常相似的问题(虽然不涉及模板):C++: How can I avoid "invalid covariant return type" in inherited classes without casting?

您的两个选择是重新设计您的解决方案,以便不再需要这种交叉依赖,或者重新设计您的解决方案,以便您只使用模板参数来声明引用和指针(因为它们的声明不需要类型的完整定义当时可用)。

【讨论】:

  • 循环依赖,无论何时潜入,通常都是设计不良的标志。重新考虑设计,要么将两者解耦,要么将它们融合。
  • @Pharap:单个类型可以定义与另一种类型的转换,因此不需要循环依赖。
  • @Pharap:不,我向你保证没有必要。假设定义了class A,那么我可以定义class B 并给它(1)一个转换构造函数B(A const&amp;) 和(2)一个转换运算符operator A() const。从那时起A 可以转换为B,反之亦然,即使A 不知道B 甚至存在。
【解决方案2】:

我认为,由于您正在对 tB::btype 进行类型定义,编译器将需要知道类型 struct MyB,而它并不知道(您只需转发声明它)。 你可以检查一下:事实上,如果你注释掉 struct B 中对 tA::atype 的引用,你仍然会得到同样的错误,而如果你注释掉 struct A 中的 typedef typeB,编译器不会抱怨。

抛开这些,你确定你需要这样的循环依赖吗?

【讨论】:

    【解决方案3】:

    如果你摆脱了模板烟幕,你在这里所拥有的就是无限递归。目前,将继承视为一种稍微不同的描述包容的方式(确实如此)。您是说 myA 包含一个 myB,而后者又包含一个 myA,而后者又包含一个 myB,以此类推——即任何一种类型的任何单个对象都具有无限大小...

    编辑:正如 litb 所指出的,这些结构都不包含任何内容,因此理论上它们不占用任何空间(感谢空基类优化)。虽然这确实可以防止结构 它们自己 具有无限大小,但编译器必须为其生成的 AST 仍然是无限的——例如,myA::myB::myA::myB: :myA::myB::myA::myB ...myB::btype(myA::atypemyA::tAmyB::tB 的最后一项)是任何嵌套级别的有效类型名称。至少按照通常编写的编译器,AST 中不允许有循环,只剩下无限的 AST 作为唯一选择。

    【讨论】:

    • 虽然我自己之前弄错了(我认为这是一些毛茸茸的关系),但我在这里看不到无限大小。 myB 包含 float 类型定义,myA 包含 float 类型定义。它们不包含彼此的数据。
    猜你喜欢
    • 1970-01-01
    • 2013-03-26
    • 2013-05-29
    • 2013-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-06
    相关资源
    最近更新 更多