Boost logo

Boost Users :

Subject: Re: [Boost-users] Incomplete types and intrusive_ptr
From: Dominique Devienne (ddevienne_at_[hidden])
Date: 2009-05-12 17:59:22


On Tue, May 12, 2009 at 3:11 PM, Peter Dimov <pdimov_at_[hidden]> 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;
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net