I am having an issue with cyclic dependencies with template classes. I have something similar to the following,
// A.hxx
template<typename T>
class B;
template<typename T>
class C;
template<typename T>
class A
{
A(T const& x, T const& y, T const& z)
{
data[0] = x;
data[1] = y;
data[2] = z;
}
A(B<T> const& b) :
A(b.x(),b.y(),b.z())
{}
A(C<T> const& c) :
A(c.x(),c.y(),c.z())
{}
T x() {return data[0];}
T y() {return data[1];}
T z() {return data[2];}
T data[3];
};
// B.hxx
template<typename T>
class A;
template<typename T>
class C;
template<typename T>
class B
{
B(T const& y, T const& z, T const& x)
{
data[0] = y;
data[1] = z;
data[2] = x;
}
B(A<T> const& a) :
B(a.y(),a.z(),a.x())
{}
B(C<T> const& c) :
B(c.y(),c.z(),c.x())
{}
T x() {return data[2];}
T y() {return data[0];}
T z() {return data[1];}
T data[3];
};
// C.hxx
template<typename T>
class A;
template<typename T>
class B;
template<typename T>
class C
{
C(T const& z, T const& x, T const& y)
{
data[0] = z;
data[1] = x;
data[2] = y;
}
C(A<T> const& a) :
C(a.z(),a.x(),a.y())
{}
C(B<T> const& b) :
C(b.z(),b.x(),b.y())
{}
T x() {return data[1];}
T y() {return data[2];}
T z() {return data[0];}
T data[3];
};
The forward declarations do not work. I have tried breaking the definitions out of the declaration and including the relevant hxx file after declaring the class, but no luck either. Any help would be appreciated. Thanks
In that special case, I would try to remove the cyclic dependancy by using interfaces or superclasses. Basics: to remove the cyclic dependancy, each real class inherits from a superclass that only declares methods that are used in other classes. It might implement the ones that do not depend on other classes, or be a mere interface (only virtual methods). The only rule is that you must only use pointers or reference to object of other classes to avoid the slicing problem. Here it is simpler because all classes inherit from a common one, but in a more general use case, each could have its own superclass. It could be:
D.hxx
#ifndef _D
#define _D
template<typename T>
class D {
public:
virtual T x() const = 0;
virtual T y() const = 0;
virtual T z() const = 0;
virtual ~D() = 0; // better to add a virtual destructor...
};
#endif
that way, the other files become (say for A.hxx):
#include "d.h"
template<typename T>
class A: public D<T>
{
public:
A(T const& x, T const& y, T const& z)
{
data[0] = x;
data[1] = y;
data[2] = z;
}
A(class D<T> const& d): A(d.x(), d.y(), d.z()) {} // for C++11 and above...
T x() const { return data[0]; }
T y() const { return data[1]; }
T z() const { return data[2]; }
private:
T data[3];
};
It works here, because you only use references of objects from other classes, so you only need the declarations. But I cannot know whether it can apply to your real use case.
Anyway as already said, the common superclass was only used here because it was simple, but you could use one interface or superclass per class
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With