C++ 模板相互依赖
模板 结构A{ typedef浮动atype; typedef typename tB::b类型typeB; }; 模板 结构B{ typedef float btype; typedef typename tA::atype typeA; };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”的使用无效 基本上,编译器无法
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[])
{
}