Solving circular dependency

Viewed 94

I know there are a couple of circular dependency issues out there, but I just couldn't solve this one.
I have two classes: Manager and Managed. Manager creates Managed objects and Managed basically wraps a couple of Manager methods and some of them are templated.

// Manager.h
struct Manager {

    Managed create(); // To be defined in the .cpp
    
    template <typename T>
    Managed create() {
        Managed managed(this); // Access Managed constructor
        managed.whatever<T>(); // Access templated function
        managed.whateverElse();
        return managed;
    }   
}

struct Managed {
    explicit Managed(Manager* manager) : manager(manager) {}
    
    template <typename T>
    void whatever() {
        manager->... // use the Manager pointer for whatever purpose
    }
    
    void whateverElse(); // To be defined in the .cpp

    Manager* manager;
}

It is a static library project, for any sake.
Also, real code can be found here.

Is there any way to solve this?

2 Answers

I just reorder your code and used PIMPL then I build a small example:

#include <iostream>

struct Managed;
struct Manager;

struct Managed {
    explicit Managed(Manager* manager) : manager(manager) {}

    template <typename T>
    void whatever() { }

    void whateverElse(); // To be defined in the .cpp

    Manager* manager;
};


struct Manager {

    Managed create(); // To be defined in the .cpp

    template <typename T>
    Managed* create() {
        Managed* m = new Managed(this);// Access Managed constructor
        m->whatever<T>(); // Access templated function
        m->whateverElse();
        return m;
    }
};

It can compile that way. But in any case should consider such designs better.

The first thing to change when struggling with dependencies is to move all implementation after all declarations, but you implement the method inside the class. Instead do the implementation after the Managed class.
Next is to provide forward declaration of all classes. I.e. start with

struct Managed;
struct Manager;

I will quote from Johns answer to provide more code details.
(John was kind enough to delete his answer when he realised that I wanted to turn my comment into one. Thanks. I quote explicitly, because I would seem like doing so implicitly anyway, writing extremely similar code.) John kindly stated that compiling this is possible.

struct Managed;

struct Manager {

    Managed create(); // To be defined in the .cpp
    
    template <typename T>
    Managed create();
};

struct Managed {
    explicit Managed(Manager* manager) : manager(manager) {}
    
    template <typename T>
    void whatever();
    
    void whateverElse(); // To be defined in the .cpp

    Manager* manager;
};

template <typename T>
Managed Manager::create() {
    Managed managed(this); // Access Managed constructor
    managed.whatever<T>(); // Access templated function
    managed.whateverElse();
    return managed;
}   

template <typename T>
void Managed::whatever() {
    manager->create();
}
Related