Boost logo

Boost :

From: Fernando Cacciola (fcacciola_at_[hidden])
Date: 2001-12-21 11:05:10


----- Original Message -----
From: Fernando Cacciola <fcacciola_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Friday, December 21, 2001 12:21 PM
Subject: RE: [boost] BCB5, the pimpl idiom bug and the new Unit Test
Framework

>
>
> Well, using plain old raw pointers won't be thread safe, but safer in any
> other respect...
> So I think that you are right, by now, better stick to raw pointers....
>

On second thought, this conclusion leads me back to my original proposal:
use the technique of grin_ptr<> with
scoped_ptr<>.

It doesn't make sense to change scoped_ptr<> though, but if gennadiy adds
the following smart ptr to some header (like unit_test_config) as an
implementation detail, he doesn't need to use bare pointers and this smart
ptr being pretty simple shouldn't present any maintenance problems:

// ginning_ptr<> is a fusion of boost::scoped_ptr<> and grin_ptr<> (*1)
//
// (*1) Alan Griffith,
(http://www.octopull.demon.co.uk/arglib/TheGrin.html)
//
// ginning_ptr mimics a built-in pointer except that it guarantees deletion
// of the object pointed to, either on destruction of the ginning_ptr or
via
// an explicit reset(). ginning_ptr is a simple solution for the
implementation
// of the PIMPL idiom that works with the Borland compiler (unlike
scoped_ptr);
//
// Alan's technique allows the compiler to parse ~ginning_ptr() without
compiling
// delete p ; and therefore without problems if T is an incomplete type,
// which is the case with the pimpl idiom.
// delete p is parsed only when ginning_ptr<> is constructed, which in the
// case of the pimpl idiom is on the implementation file when T is
complete.
//
// Since ~ginning_ptr() doesn't see (statically) "delete p", this smart
pointer
// allows the pimpl idiom to be safely implemented even for Borland C++
5.5.1
// (which erroneously parses the pimpl destructor while T is still
incomplete)
//
// NOTE: checked_delete(p) is used instead of delete p to catch the
// case where the constructor of the outer handle class is visible
// before T is complete
// (something that should happen in a pimpl implementation)
//
template<typename T> class ginning_ptr : noncopyable {

  T* ptr;
  typedef void (*do_delete_func) ( T* p ) ;
  do_delete_func do_delete ;
  static void do_delete_impl( T* p ) { checked_delete(p) ; }

 public:
  typedef T element_type;

  explicit ginning_ptr( T* p=0 ) : ptr(p) , do_delete(do_delete_impl) {} //
never throws
  ~ginning_ptr() { do_delete(ptr); }
  void reset( T* p=0 ) { if ( ptr != p ) { do_delete(ptr); ptr =
p; } }
  T& operator*() const { return *ptr; } // never throws
  T* operator->() const { return ptr; } // never throws
  T* get() const { return ptr; } // never throws
#ifdef BOOST_SMART_PTR_CONVERSION
  // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
  operator T*() const { return ptr; } // never throws
#endif
  }; // ginning_ptr

I've received email from Alan Griffith and he said that we have permission
to use his ideas as long as we don't involve him directly; that is, as long
as we handle it ourselves.
I don't think that the deep copy semantics of grin_ptr<> or impl_ptr<> are
needed here, only the callback delete, so grinning_ptr<> is very simple and
easy to maintain.

Fernando Cacciola
Sierra s.r.l.
fcacciola_at_[hidden]
www.gosierra.com


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