Reputation: 6296
I'm using boost::intrusive_ptr
as my reference counted smart pointer. I'm using something like this:
This seems a good idea, because it simplifies the declaration of a new Reference counted class, just inheriting from it. The problem comes with forward declarations. There are a lot of places where I want to use a pointer to a type not yet decladed in a class definiton and it is not possible, because the 2 methods that handle ref count need to know if the type inherits from CRefCounted or not.
If I try to include the dependencies before the declaration of the intrusive_ptr it is ok, but then, I get a lot of cyclic includes.
How would you handle this scenario?
Upvotes: 2
Views: 1183
Reputation: 5176
I've been using a similar RefCounted base class a lot and I started wondering why do I never have this problem. And it's because I tend to hide implementation details in source files. Consider the following header file of class B:
//File: B.h
#include <boost/intrusive_ptr.hpp>
class A;
class B
{
public:
B();
~B();
boost::intrusive_ptr<A> foo();
void foo2(const boost::intrusive_ptr<A> p);
boost::intrusive_ptr<A> p;
};
It works, because even though it is using intrusive_ptr, it doesn't need to instantiate its constructor or destructor. Therefore it doesn't need to know anything about the class A.
The place where it needs to know about A is in the source file. (And also in places where foo/foo2 are called). B's constructor and destructor implicitly call intrusive_ptr< A>'s constructor/destructor, so A's definition must be available.
//File: B.cpp
#include "B.h"
#include "A.h" //Include header where A is defined.
B::B() { }
B::~B() { }
//Other member functions...
I don't know if this helps in your case, but it's something to think about. :)
Upvotes: 0
Reputation: 29174
I think you can solve this using templates functions for intrusive_ptr_add_ref
and intrusive_ptr_release
as follows:
namespace boost {
template<class T> void intrusive_ptr_add_ref(T* p) { ++(p->references) }
template<class T>void intrusive_ptr_release(T* p) {
if (--(p->references) == 0)
delete p
}
};
You'll also need to adapt the friend declarations in CRefCounted
like
template class<T> friend void ::boost::intrusive_ptr_add_ref(T*);
template class<T> friend void ::boost::intrusive_ptr_release(T*);
Using these declarations, you can use intrusive_ptr
on forward-declared classes like
class A;
class B {
::boost::intrusive_ptr<A> _myPtr;
};
class A : public CRefCounted {
};
This solution has the drawback (theoretically...), that you define a pair of add_ref
/release
functions for every subclass of CRefCounted
, but I think that the compiler will choose to use inlining anyway, so this can be neglected.
Upvotes: 3