Boost logo

Boost :

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


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

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
    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;
      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)); }

    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

- 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

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,


Do You Yahoo!?
Send instant messages & get email alerts with Yahoo! Messenger.

Boost list run by bdawes at, gregod at, cpdaniel at, john at