Incomplete types and intrusive_ptr

Is it possible to achieve the ability of shared_ptr<T> to be used as a class member in a class declaration with an incomplete type T, with intrusive_ptr? For new code, I'm wrapping classes in shared_ptr, instead of deriving from our refcounted base class. I've also started to use intrusive_ptr for all the legacy code that already derives from RefCountedBase, but unlike shared_ptr I'm forced to #include the header for the type wrapped in the intrusive_ptr, something I'd like to avoid, to reduce build times. Isn't it possible to have a mix of shared_ptr and intrusive_ptr which also captures a Destructor instance when the intrusive_ptr is assigned, similarly to what shared_ptr does? Has this been considered before? Thanks, --DD PS: We have full control of RefCountedBase, so would refactoring it to use boost::detail::shared_count internally allow the change I discuss above? If so, how would one go about it?

Dominique Devienne:
Is it possible to achieve the ability of shared_ptr<T> to be used as a class member in a class declaration with an incomplete type T, with intrusive_ptr?
The usual approach is to declare: class X; void inrisuve_ptr_add_ref( X* ); void intrusive_ptr_release( X* );

On Tue, May 12, 2009 at 3:11 PM, Peter Dimov <pdimov@pdimov.com> wrote:
Dominique Devienne:
Is it possible to achieve the ability of shared_ptr<T> to be used as a class member in a class declaration with an incomplete type T, with intrusive_ptr?
The usual approach is to declare:
class X; void intrusive_ptr_add_ref( X* ); void intrusive_ptr_release( X* );
Thanks Peter. This helped me see that I need a declaration of the add_ref/release functions *per* derived class T of RefCountedBase, that I want to fwd declare to avoid including its header. Previously I just declared add_ref/release for RefCountedBase, and since the derivation is not know by just fwd decl SomeRefCounted, I was getting this error: error C2664: 'boost::intrusive_ptr_release' : cannot convert parameter 1 from 'acme::SomeRefCounted *' to 'acme::RefCountedBase *' and wrongly assumed intrusive_ptr<T> required a complete T. I've summarized the issue I was having below. Thanks again for your help. Regards, --DD // in refcountedbase.h namespace acme { class RefCountedBase { public: void ref() { ++refcount_; } void unref() { if (--refcount_ == 0) { cleanup(); delete this; } } static void ref(RefCountedBase* r) { if (r) r->ref(); } static void unref(RefCountedBase* r) { if (r) r->unref(); } protected: RefCountedBase() : refcount_(0) {} RefCountedBase(const RefCountedBase&) : refcount_(0) {} virtual ~RefCountedBase() {} virtual void cleanup() {} private: RefCountedBase& operator=(const RefCountedBase&); private: int refcount_; }; } // in acme/intrusive_ptr.h #include <boost/intrusive_ptr.hpp> namespace acme { using boost::intrusive_ptr; inline void intrusive_ptr_add_ref(acme::RefCountedBase* r) { acme::RefCountedBase::ref(r); } inline void intrusive_ptr_release(acme::RefCountedBase* r) { acme::RefCountedBase::unref(r); } } // in acme/foobar.h // #include <acme/intrusive_ptr.h> namespace acme { class SomeRefCounted; #ifdef DO_FWD_DECL_SOMEREFCOUNTED_HELPERS void intrusive_ptr_add_ref(SomeRefCounted* r); void intrusive_ptr_release(SomeRefCounted* r); #endif class FooBar { intrusive_ptr<SomeRefCounted> some_; // WAS GETTING COMPILE ERROR HERE }; } #ifdef DO_INCLUDE_SOMEREFCOUNTED_H // in acme/somerefcounted.h // lots of #include namespace acme { class SomeRefCounted : public RefCountedBase {}; inline void intrusive_ptr_add_ref(SomeRefCounted* r) { acme::RefCountedBase::ref(r); } inline void intrusive_ptr_release(SomeRefCounted* r) { acme::RefCountedBase::unref(r); } }; #endif void intrusive_ptr(int /*argc*/, const char* /*argv*/[]) { using namespace acme; FooBar foobar; }
participants (2)
-
Dominique Devienne
-
Peter Dimov