C++ 模板相互依赖

C++ 模板相互依赖,c++,templates,instantiation,C++,Templates,Instantiation,模板 结构A{ typedef浮动atype; typedef typename tB::b类型typeB; }; 模板 结构B{ typedef float btype; typedef typename tA::atype typeA; }; structmyb; 结构MyA:公共A{}; 结构MyB:公共B{}; int main(int argc,char*argv[]) { } 不编译,因为 main.cpp:6:错误:不完整类型“struct MyB”的使用无效 基本上,编译器无法

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

structmyb;
结构MyA:公共A{};
结构MyB:公共B{};
int main(int argc,char*argv[])
{
}
不编译,因为 main.cpp:6:错误:不完整类型“struct MyB”的使用无效

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

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


放在一边,你确定你需要这样的循环依赖吗

这无法直接解决。昨天发布了一个非常类似的问题(尽管不涉及模板):


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

如果您去掉了模板烟雾屏,那么这里的内容将涉及无限递归。目前,将继承看作是一种稍微不同的表示包容的方式(事实就是这样)。你是说一个myA包含一个myB,而myB又包含一个myA,myA又包含一个myB,以此类推——也就是说,任何一种类型的单个对象都有无限大


编辑:正如litb指出的,这两个结构都不包含任何内容,因此在理论上,它们不占用任何空间(由于空的基类优化)。虽然这确实可以防止结构本身具有无限大小,但编译器必须为其中一个生成的AST仍然是无限的——例如,myA::myB::myA::myB::myA::myB::myB…myB::btype(myA::atype、
myA::tA
myB::tB
的最后一项)是任何嵌套级别的有效类型名。至少在通常编写编译器的情况下,AST中不允许循环,留下无限AST作为唯一的选择。

结构MyB定义在哪里?您可以做的是制作
MyA
MyB
模板:
template struct MyBT;模板结构MyAT:public A{};模板结构MyBT:B{};typedef MyAT MyA;typedef-MyBT-MyB。但是这个解决方案很难看:“很遗憾,看起来我上面提出的代码在当前C++中是不正确的。然而,目前有一份问题报告似乎使这一观点形成了良好的形式。虽然提议的措辞让我感到头疼:)虽然我自己以前弄错了(我认为这是一种毛茸茸的关系),但我在这里看不到无限大
myB
包含一个
float
typedef,而
myA
包含一个
float
typedef。它们不包含彼此的数据。循环依赖关系,无论何时潜入,通常都是臭烘烘的设计的标志。重新考虑设计,要么将两者解耦,要么将它们融合。@Pharap:一个类型可以定义与另一个类型之间的转换,因此不需要循环依赖关系。@Pharap:不,我向您保证,没有必要。假设定义了
类A
,那么我可以定义
类B
,并给它(1)一个转换构造函数
B(常数&)
,和(2)一个转换运算符
运算符A()常数。从那时起,
A
可以转换为
B
,反之亦然,尽管
A
甚至不知道
B
的存在。
struct MyB;
struct MyA: public A<MyB>{};
struct MyB: public B<MyA>{};

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