Loop dependencies in the template

I have a problem with circular 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];
};

Advanced declarations do not work. I tried to break the definitions from the declaration and include the corresponding hxx file after the class declaration, but no luck. Any help would be greatly appreciated. Thanks

+4
source share
5 answers

, : . , . , ( ), .

, , , , . A.h file (untested):

#ifndef A_H
#define A_H

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(C<T> const& c);

    T x() {return data[0];}
    T y() {return data[1];}
    T z() {return data[2];}

    T data[3];
};

#include <B.h>
#include <C.h>

template<typename T>
inline A::A(B<T> const& b) :
    A(b.x(),b.y(),b.z())
{}

template<typename T>
inline A::A(C<T> const& c) :
    A(c.x(),c.y(),c.z())
{}

#endif

B C, A.h, B.h C.h, .

+2

. : , , , . , , ( ). , , . , , . :

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

, (, 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];
};

, , . , .

, , , ,

+3

, B . :

A(B<T> const& b) :      // B<T> should be better than B
 A(b.x(),b.y(),b.z())
{}

EDIT:

:

template <class T>
class A;

template <class T>
class B;


template <class T>
class A
{
    void func(B<T> par) {
        par.func(this);
    }
};

template <class T>
class B
{
    void func(A<T> par) {
        par.func(this);
    }
};

EDIT2:

:

// A.h
template <class T>
class B;

template <class T>
class A
{
  public:
    void func(B<T>& par) {
        par.func(*this);
    }
};

// B.h
template <class T>
class A;

template <class T>
class B
{
    void func(A<T> par) {
        par.func(*this);
    }
};

// main.cpp
#include "a.h"
#include "b.h"

int main()
{
    A<int> a;
    B<int> b;
    a.func(b);
}
+2

, , , -:

  • .

  • You cannot have circular dependencies, with or without patterns. To get around this, a class can only have pointers or references to the dependent class in the header. Then the class cpp file may include the header of the dependent file.

0
source

You do not provide valid template type names. For example, this constructor:

A(B const& b) :

it should be:

A(B<T> const& b) :
0
source

Source: https://habr.com/ru/post/1616584/


All Articles