Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
439 views
in Technique[技术] by (71.8m points)

c++ - Two template classes being composed of a member of each other

I have a need in my code for two template classes to be composed of a member field of each other. For example, I have two files,

templates.h

template <class T> class B;

template <class T>
class A
{
    B<A> a;

    // fields and methods dependent on T
};

template <class T>
class B
{
    A<B> b;

    // fields and methods dependent on T
};

main.cpp

#include "templates.h"

int main()
{
    A<int> a;
}

When I compile I receive the output shown in this link

http://pastebin.com/taBWZjar

I am using the g++ compiler. When I type g++ --version, I get

g++ (Gentoo 4.7.2 p1.3, pie-0.5.5) 4.7.2

If this is not possible to do in c++, what is an alternative or work around? Or perhaps is this a bug with my compiler?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Your current design contains a serious flaw which is known as circular dependency. It will never compile, and the best way to fix it is to redesign your class hierarchy.

To give you the clue why it can never compile, lets simplify the situation by removing templates:

class B;

class A {
  B b;
};

class B {
  A a;
};

Now try to think as a compiler. To know how much space is needed for allocation of class A (and compiler has to know that at compile-time), it needs to know how much space is needed for allocation of class B, and vice versa. Clearly, this is a circular dependency. You can try to compile it yourself and see that compiler complains about it.

One possible way to fix that would be switching to pointers (or references):

class B;

class A {
  B* b; // B& b; is possible too
};

class B {
  A a;
};

This should compile just fine. The reason is that now the compiler knows that b is a pointer, and the space needed to accommodate that pointer is fixed (4 bytes for 32-bit targets, and 8 bytes for 64-bit targets accordingly).

NOTE: Pointer/reference to a in B is unnecessary because A is already defined at that point, and therefore we can use it as a direct member in B.

In your situation you complicated things even further with templates, and while you could utilize the proposed fix (using pointers/references) and combine it with templates, I don't recommend it. Your code has to be totally redesigned.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...