#ifndef HOLDER_PTR_H
#define HOLDER_PTR_H

// ----------------------------------------------------------------------
//
// HolderPtr.h - Smart pointer permitting copying of pointed-to object
//
// Purpose:
//   Declaration and definition of the class template zmt::HolderPtr<T>.
//   Full documentation available at
//     http://www.peerdirect.com/resources/gotw062a.html;
//
// History:
//   08-May-2000  WEB  Original version by Herb Sutter, GOTW #62,
//     http://www.gotw.ca/gotw/062.htm; edit for comformance with Zoom
//     and ISOcxx
//   06-Apr-2001  WEB  Fix syntax for declaring class template friendship
//   31-May-2002  WEB  Add swap() free function
//
// ----------------------------------------------------------------------


#include "ZMutility/ZMenvironment.h"

#include <algorithm>  // for std::swap()


ZM_BEGIN_NAMESPACE( zmt )


  // --------------------------------------------------------------------
  //
  // Auxiliary traits class template providing default clone()
  // Specialize for types having their own self-copy operations
  //
  // --------------------------------------------------------------------


  template< class T >
  struct HPTraits  {

    static  T *  clone( T const * p )  { return new T( *p ); }

  };  // HPTraits


  // --------------------------------------------------------------------
  //
  // Copyable smart pointer class template
  //
  // --------------------------------------------------------------------


  template< class T >
  class HolderPtr  {

  public:

    // ----------------------------------------
    // Default constructor/destructor:
    // ----------------------------------------

    explicit HolderPtr( T * p = 0 ) : myP( p )  { ; }
    ~HolderPtr()  { delete myP; myP = 0; }

    // ----------------------------------------
    // Copy constructor/copy assignment:
    // ----------------------------------------

    HolderPtr( HolderPtr const & orig )
    : myP( createFrom( orig.myP ) )  { ; }

    HolderPtr &  operator = ( HolderPtr const & orig )  {
      HolderPtr<T>  temp( orig );
      swap( temp );
      return *this;
    }

    // ----------------------------------------
    // Access mechanisms:
    // ----------------------------------------

    T &  operator *  () const  { return *myP; }
    T *  operator -> () const  { return  myP; }

    // ----------------------------------------
    // Manipulation:
    // ----------------------------------------

    void  swap( HolderPtr & orig )  { std::swap( myP, orig.myP ); }

    // ----------------------------------------
    // Construct/assign from compatible HP<>:
    // ----------------------------------------

    template< class U >
    HolderPtr( HolderPtr<U> const & orig )
    : myP( createFrom( orig.myP ) )  { ; }

    template< class U >
    HolderPtr &  operator = ( HolderPtr<U> const & orig )  {
      HolderPtr<T>  temp( orig );
      swap( temp );
      return *this;
    }

  private:

    // ----------------------------------------
    // Implementation aid:
    // ----------------------------------------

    template< class U >
    T *  createFrom( U const * p ) const  {
      return p
           ? HPTraits<U>::clone( p )
           : 0;
    }

    // ----------------------------------------
    // Grant full privileges to other HP<>'s:
    // ----------------------------------------

    template< class U >
    friend class HolderPtr;

    // ----------------------------------------
    // Member data:
    // ----------------------------------------

    T *  myP;

  };  // HolderPtr


  // --------------------------------------------------------------------
  //
  // Free-standing swap()
  //
  // --------------------------------------------------------------------

  template< class T >
  inline
  void  swap(  HolderPtr<T> & hp1, HolderPtr<T> & hp2 )  {
    hp1.swap( hp2 );
  }


ZM_END_NAMESPACE( zmt )

#endif  // HOLDER_PTR_H
