Luchian Grigore
Luchian Grigore

Reputation: 258618

Is using two identical typedefs bad and how to avoid it?

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

Answers (3)

user450018
user450018

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

thiton
thiton

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

Samuel Harmer
Samuel Harmer

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

Related Questions