I ran into circular dependency when designing two classes, let's call them Foo
and Baz
, that both contain function templates. To solve it I removed the include statements from the top of both the headers, and then used .inl
-files to implement the function templates, that I then included at the bottom of the class headers. The headers could then simply have forward declarations and the .inl
files could do the including, making sure that both classes were defined before any member functions were implemented.
Simple enough, right? Well, not quite.
Foo
needs to have one of Baz
's member functions as a friend (for the purpose of this question, assume that this is a requirement and not something that I can change). Meaning I can't use a forward declaration of Baz
to declare the friendship, I need the actual header where the Baz
is defined.
class Baz;
class Foo
{
template<typename T>
friend void Baz::templateFunc(Foo&); // Error
};
After a long series of attempted solutions, I've come up with the following:
baz.h
#pragma once
class Foo;
class Baz
{
public:
template<typename T>
void templateFunc(Foo& f);
};
#ifndef FOO_H // If this header was not included by foo.h...
#include "baz.inl" // ...then include the inline file
#endif
baz.inl
#define BAZ_INL
#include "foo.h"
template<typename T>
void Baz::templateFunc(Foo& f)
{
...
}
foo.h
#ifndef FOO_H
#define FOO_H
#include "baz.h"
class Foo
{
template<typename T>
friend void Baz::templateFunc(Foo&);
...
// Some function templates that are implemented in foo.inl
};
#include "foo.inl"
#ifndef BAZ_INL
#include "baz.inl"
#endif
#endif
(foo.inl
is not important here)
This solution works but I'm not very satisfied with it. First of all, it looks very messy to me. Someone going through these headers would probably be confused as to why baz.h
checks if another header has been defined before implementing its functions and why foo.h
is including the implementation of baz.h
. It seems like a busy solution just for satisfying a friend declaration.
Is there a simpler solution for this type of circular dependency?