Reputation: 258618
Because of circular dependencies, you use forward declarations for some classes:
//B.h
class A;
class B
{
public:
void foo(A* a);
};
typedef SmartPtr<B> BPtr;
//A.h
class B;
class A
{
public:
void foo(B* b);
};
typedef SmartPtr<A> APtr;
Now, let's say I want to change the prototypes of the functions to use smart pointers:
void A::foo(BPtr b);
void B::foo(APtr a);
Obviously, I can't forward declare APtr
or BPtr
. What works is re-using the typedef
:
//B.h
class A;
typedef SmartPtr<A> APtr;
class B
{
public:
void foo(APtr a);
};
typedef SmartPtr<A> APtr;
//A.h
class B;
typedef SmartPtr<B> BPtr;
class A
{
public:
void foo(BPtr b);
};
typedef SmartPtr<A> APtr;
but I'm not sure if this is the right solution. Is there a standard way of doing this? Is what I did wrong or dangerous?
Upvotes: 2
Views: 871
Reputation: 148
The question basically boils down to whether this code is OK:
#include <memory>
struct A;
typedef std::unique_ptr<A> APtr;
struct A {};
typedef std::unique_ptr<A> APtr;
...where std::unique_ptr could be replaced by some other smart pointer class.
A typedef is a declaration, and you can have as many declarations as you like of the same name in the same declarative region, as long as they declare that name to be exactly the same thing, for example something like this:
extern int i;
extern int i;
extern int i, i, i, i, i, i, i;
In your case they do - they both declare APtr as an alias for std::unique_ptr<A>. That A is an incomplete type in one declaration and a complete one in the other does not matter, since completeness of A is not needed for this declaration (and if it was you would have got a compilation error at the point of the first typedef).
In short: it works because you're not really "re-using" the typedef, you're just declaring the same typedef multiple times, which is fine.
Upvotes: 2
Reputation: 36049
Declare smart pointers and class forwards once in a common header and include it:
fwd.h:
class A;
class B;
typedef SmartPtr<A> APtr;
typedef SmartPtr<B> BPtr;
A.h:
#include "fwd.h"
struct A {
void foo(BPtr a);
};
Upvotes: 2
Reputation: 4412
Assuming you've got a good reason for these cyclical dependencies, why not do:
// defs.h
class A;
class B;
typedef SmartPtr<A> APtr;
typedef SmartPtr<B> BPtr;
//B.h
#include "defs.h"
class B
{
public:
void foo(APtr a);
};
//A.h
#include "defs.h"
class A
{
public:
void foo(BPtr b);
};
Upvotes: 3