keebus
keebus

Reputation: 1010

Specialized template classes cyclic dependency

I have a daunting design problem and I'm begging for some advice. To put it real short, I have two base classes A and B, and AImpl<T> and BImpl<T> inheriting from A and B respectively. What I need is to retrieve a (static) BImpl<T>* from a AImpl<T> object pointed by a polymorphic A* pointer, but without explicitly adding something like virtual B* getB() in A and overriding it in AImpl<T> because B and BImpl<T> already depend on A and that would add a cyclic dependency. Both AImpl<T> and BImpl<T> are specialized for primitive types, std::string, T*, etc.

Any good advice?

Edit: forward declaration is not useful here because even adding the f.d. of B in A.h and putting the method virtual B* getB() in A, being AImpl a template class, it would require a full definition of the method. getB() should return a static instance of BImpl.

To explain the problem in other terms, this is what happens: in a user cpp I include A.h and use A classes. Suppose AImpl has the method getB() defined as

const B* getB() const {
   static BImpl<T> instance;
   return &instance;
}

this method requires full inclusion of B.h, leading to cyclic dependency.

Edit 2, full code example I'll try to put it to a simple code example, hoping to better explain my concern.

// File A.h
struct A
{
  virtual ~A();
  void const A* getChild() const { /* ... */}
  virtual const B* getB() const = 0;
};

template <typename T>
struct AImpl : public A
{
  const B* getB() const
  {
    return getBImpl_of<T>();
  }
};

// Specializations of AImpl<T>

template<typename T>
const A* getAImpl_of()
{
  static AImpl<T> instance;
  return &instance;
}

// File B.h
struct B
{
  template<typename T>
  static void work()
  {
    getBImpl_of<T>()->doWork();
  }

  virtual ~B();

protected:
  virtual void doWork() = 0;
};

template <typename T>
struct BImpl : public B
{
protected:
  void doWork()
  {
    const A* pA = getAImpl_of<T>();

    // ... do something with pA ...

    // Here is the key point:
    const A* pChild = pA->getChild();
    pChild->getB()->doWork();
  }
};

template<typename T>
const B* getBImpl_of()
{
  static BImpl<T> instance;
  return &instance;
}

This is what I would like to do, but obviously including A.h in B.h and vice-versa leads to cyclic dependency. Note this is not exactly what I have, but shows the same problem. Thank you.

Upvotes: 2

Views: 173

Answers (1)

Vaughn Cato
Vaughn Cato

Reputation: 64308

Forward declaration should be fine, since template methods aren't instantiated until they are used.

Try putting this at the top of your A.h:

struct B;
template <typename T> const B* getBImpl_of();

then you can include A.h from within B.h.

Upvotes: 1

Related Questions