Boost logo

Boost :

From: Dietmar Kuehl (dietmar_kuehl_at_[hidden])
Date: 2000-05-04 16:13:52


Hi,

I haven't paid close attention to the various discussions on smart
pointers but I want to use one in the rewrite of the directory iterator
I'm currently doing. The need for a smart pointer arises due to the
internal representation of the directory iterators: To make the header
independent from system headers, the actual representation is only
declared in the implementation file and a pointer to the representation
is stored in the actual iterator. The representation can be shared
between multiple copies of an iterator very much like the stream
iterators share a common stream or stream buffer but with the iterators
being responsible for releasing the allocated memory.

At first sight, 'shared_ptr' seemed to be the right approach.
Unfortunately, it is not for one of two reasons:

- A simple forward declaration to the internal representation is
  insufficient or would require implemenation of some members I was
  hoping I don't have to write (ie. dtor and copy assignment). This is
  because the definition of the internal representation needs to be
  available if the object is destructed.

- Using a base class with a virtual destructor which is defined in the
  public header and deriving the representation from this base would
  basically work but would litter the code using the smart pointer with
  casts.

As a result, I decided that the smart pointers currently available are
unfortunately not suitable for my purpose and I hacked another one
which I called 'pimpl_ptr' for now:

  struct pimpl_base
  {
    pimpl_base(): m_count(0) {}
    virtual ~pimpl_base() {}
    int m_count;
  };

  template <class Pimpl>
  class pimpl_ptr
  {
  public:
    pimpl_ptr(Pimpl* ptr): m_ptr(ptr) { ++(m_ptr->m_count); }
    pimpl_ptr(pimpl_ptr const& ptr): m_ptr(ptr.m_ptr) {
      ++(m_ptr->m_count); }
    ~pimpl_ptr() { if (--(m_ptr->m_count) == 0) delete m_ptr; }
    pimpl_ptr& operator= (pimpl_ptr const& ptr) {
      pimpl_base* del = m_ptr;
      m_ptr = ptr.m_ptr;
      ++(m_ptr->m_count);
      if (--(del->m_count) == 0)
        delete del;
    }
    Pimpl& operator*() const { return *static_cast<Pimpl*>(m_ptr); }
    Pimpl* operator->() const { return static_cast<Pimpl*>(m_ptr); }

    template <class Base>
    operator pimpl_ptr<Base> () const {
      return pimpl_ptr<Base>(static_cast<Pimpl*>(m_ptr)); }

  private:
    pimpl_base* m_ptr;
  };

Basically this is supposed to work similar to 'shared_ptr' but with
two major differences:

- To use this pointer, the type has to be derived from a common base
  class which is actually the type stored inside the smart pointer:
  to obtain a pointer or a reference, the pointer is cast with
  static_cast.

- Since there is a common base class, there is a logical place where
  the count is stored, too: It is a member of the base class, ie. this
  smart pointer is somewhat intrusive but it is anyway due to the base
  class.

In Tokyo we discussed the need to organize a system of smart pointers.
Basically, it was decided that there is probably a fairly small set of
smart pointer which make candidates for the next round of
standardization, a bigger set of smart pointers making candidates for
inclusion in Boost, and the big set of all smart pointers. What
category does 'pimpl_ptr' fall into? ... or asked more generally, what
smart pointers qualify for what category? That is, what kinds of
resource management is supported by what library?

Personally, I have occasional uses of the "pimpl idiom". Sometimes
I need to share the internal implementation, at other times I don't.
For the directory iterator, I want to use a shared representation and
a pointer like the one above would come in handy.

Any thoughts?

Thank you very much,
  Dietmar

=====
<mailto:dietmar_kuehl_at_[hidden]>
<http://www.dietmar-kuehl.de/>

__________________________________________________
Do You Yahoo!?
Send instant messages & get email alerts with Yahoo! Messenger.
http://im.yahoo.com/


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk