Class A
is the sole instantiator and container of instances of class B
.
So it seemed like a good idea to make the constructor of class B
private, and call it only by a friend function declared in class B
and defined in class A
.
File A.h (EDIT: included enum defined in class B)
#ifndef A_H
#define A_H
#include "B.h"
using namespace std;
class A
{ public:
A();
shared_ptr<B> CreateBInstance( const B::ENUM_STANDARD_COLORS );
shared_ptr<B> CreateBInstance( const string ); // Custom color
private:
unique_ptr<map<int, shared_ptr<B>>> UPTR__BInstancesMap;
}
#endif
File B.h (EDIT: included enum defined in class B)
#ifndef B_H
#define B_H
#include "A.h" // Causes chaos
using namespace std;
class B
{ public:
enum class ENUM_STANDARD_COLORS : unsigned int
{ ... // ~70 standard colors
};
private:
B();
friend
shared_ptr<B> A::CreateBInstance( const ENUM_STANDARD_COLORS );
friend
shared_ptr<B> A::CreateBInstance( const string ); // Custom color
}
#endif
Class A
requires a full declaration (#include) of class B
for shared_ptr<B>
.
Class B
requires some declaration of class A
for the friend function.
A simple forward declaration causes the error:
invalid use of incomplete type 'struc A'
at the friend function declaration.
A full declaration (#include) is far worse:
error: prototype for 'std::shared_ptr A::CreateInstance()' does not match any in class 'A'
(but it does!) at the friend function declaration.
And, because class B
is now broken:
error: 'B' was not declared in this scope
error: template argument 1 is invalid
appears at every mention of B
in class A
, as well as in classes F
and G
(etc.) which #include class B
for their own use of shared_ptr<B>
.
And, because classes F
and G
are also now broken:
error: 'F' was not declared in this scope
error: template argument 1 is invalid>
error: 'G' was not declared in this scope
error: template argument 1 is invalid
appears at every mention of F
and G
in class A
.
Unfortunately, the include guards don't prevent the circular inclusion.
Is there a way to make this friend function work? I've never achieved so many errors in one go!
Class
A
requires a full declaration (#include) of classB
forshared_ptr<B>
.
No, forward declaration would be sufficient in A.h
. shared_ptr
(and unique_ptr
) won't require class B
to be complete type for return type declaration[1] and class data member declaration.
File A.h
#ifndef A_H
#define A_H
class B; // forward declaration
using namespace std;
class A
{ public:
A();
shared_ptr<B> CreateBInstance();
private:
unique_ptr<map<int, shared_ptr<B>>> UPTR__BInstancesMap;
};
#endif
[1] It's also true for "regular" type T
which isn't shared_ptr
.
In A header file, you can simply tell the compiler that an type B exists and it needs to look for it while linking. To do so, replace
#include "B.h"
by
class B;
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