开发者

Template mutual dependence

template struct A{ typedef float atype; typedef typename tB::btype typeB; }; template struct B{ typedef float btype; typedef typename tA::atype typeA; };

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

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

does not compile because "m开发者_如何学Pythonain.cpp:6: error: invalid use of incomplete type ‘struct MyB’".

Basically the compiler cannot solve the loop because definition of A depends on definition of B an viceversa. Is there a way to sort this out? thanks,


This cannot be resolved directly. There was a very similar question (although not involving templates) posted yesterday: C++: How can I avoid "invalid covariant return type" in inherited classes without casting?

Your two options are to redesign your solutions so that this cross-dependency is no longer required, or to redesign your solution so that you are only using the template parameters to declare references and pointers (because their declarations do not require that a complete definition of the type is available at the time).


I think that since you are typedef'ing tB::btype the compiler would need to know the type struct MyB, which it doesn't (you only forward declared it). You can check this: in fact if you comment out the reference to tA::atype in struct B you still get the same error, while if you comment out the typedef typeB in struct A the compiler doesn't complain.

Putting that aside, are you sure that you need such a circular dependence?


If you get rid of the template smoke screen, what you have here involves infinite recursion. For the moment, think of inheritance as a slightly different way of stating containment (which it is). You're saying a myA contains a myB, which in turn contains a myA, which in turn contains a myB, and so on forever -- i.e. any single object of either type has infinite size...

Edit: as litb pointed out, neither of these structs contains anything, so in theory, they don't occupy any space (thanks to the empty base class optimization). While it's true that this can prevent the structs themselves from having infinite size, the AST the compiler would have to generate for either is still infinite -- e.g., myA::myB::myA::myB::myA::myB::myA::myB ...myB::btype (a final item of myA::atype, myA::tA, or myB::tB)is a valid type name for any level of nesting. At least as a compiler is normally written, no cycles are allowed in the AST, leaving an infinite AST as the only alternative.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜