--- /dev/null
+/* ========================================================================
+** Extended Template and Library
+** Template Smart Pointer Implementation
+** $Id$
+**
+** Copyright (c) 2002 Robert B. Quattlebaum Jr.
+**
+** This package is free software; you can redistribute it and/or
+** modify it under the terms of the GNU General Public License as
+** published by the Free Software Foundation; either version 2 of
+** the License, or (at your option) any later version.
+**
+** This package is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** === N O T E S ===========================================================
+**
+** This is an internal header file, included by other ETL headers.
+** You should not attempt to use it directly.
+**
+** ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __ETL__SMART_PTR_H
+#define __ETL__SMART_PTR_H
+
+/* === H E A D E R S ======================================================= */
+
+#include <cassert>
+#include "_ref_count.h"
+
+/* === M A C R O S ========================================================= */
+
+/* === T Y P E D E F S ===================================================== */
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+_ETL_BEGIN_NAMESPACE
+
+template <class T>
+struct generic_deleter
+{
+ void operator()(T* x)const { delete x; }
+};
+
+template <class T>
+struct array_deleter
+{
+ void operator()(T* x)const { delete [] x; }
+};
+
+// ========================================================================
+/*! \class smart_ptr _smart_ptr.h ETL/smart_ptr
+** \brief Object Smart Pointer
+** \see loose_smart_ptr
+** \writeme
+*/
+template <class T, class D=generic_deleter<T> >
+class smart_ptr
+{
+public:
+
+ typedef T value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef int count_type;
+ typedef int size_type;
+ typedef D destructor_type;
+
+#ifdef DOXYGEN_SHOULD_SKIP_THIS // #ifdef is not a typo
+private:
+#endif
+ value_type *obj; //!< \internal Pointer to object
+ reference_counter refcount;
+
+public:
+ // Private constructor for convenience
+ smart_ptr(value_type* obj,reference_counter refcount):obj(obj),refcount(refcount) { }
+
+ //! Default constructor - empty smart_ptr
+ smart_ptr():obj(0),refcount(false) {}
+
+ //! Constructor that constructs from a pointer to new object
+ /*! A new smart_ptr is created with a pointer
+ to a newly allocated object. We need
+ to be explicit with this so we don't
+ accidently have two smart_ptrs for one
+ object -- that would be bad. */
+ explicit smart_ptr(value_type* x):obj(x),refcount(x?true:false) { }
+
+ //! Template copy constructor
+ /*! This template constructor allows us to cast
+ smart_ptrs much like we would pointers. */
+#ifdef _WIN32
+ template <class U>
+ smart_ptr(const smart_ptr<U> &x):obj((pointer)&*x.obj),refcount(x.refcount())
+ { }
+#endif
+
+ //! Default copy constructor
+ /*! The template above is not good enough
+ for all compilers. We need to explicitly
+ define the copy constructor for this
+ class to work on those compilers. */
+ smart_ptr(const smart_ptr<value_type> &x):obj(x.obj),refcount(x.refcount) { }
+
+ explicit smart_ptr(const value_type &x):obj(new value_type(x)) { }
+
+ //! smart_ptr is released on deletion
+ ~smart_ptr() { if(refcount.unique()) destructor_type()(obj); }
+
+ //! Template Assignment operator
+ template <class U> const smart_ptr<value_type> &
+ operator=(const smart_ptr<U> &x)
+ {
+ if(x.get()==obj)
+ return *this;
+
+ reset();
+
+ if(x.obj)
+ {
+ obj=(pointer)x.get();
+ refcount=x.refcount;
+ }
+
+ return *this;
+ }
+
+ //! Assignment operator
+ const smart_ptr<value_type> &
+ operator=(const smart_ptr<value_type> &x)
+ {
+ if(x.get()==obj)
+ return *this;
+
+ reset();
+
+ if(x.obj)
+ {
+
+ obj=(pointer)x.get();
+ refcount=x.refcount;
+ }
+
+ return *this;
+ }
+
+ //! smart_ptr reset procedure
+ void
+ reset()
+ {
+ if(obj)
+ {
+ if(refcount.unique()) destructor_type()(obj);
+ refcount.detach();
+ obj=0;
+ }
+ }
+
+ void spawn() { operator=(smart_ptr(new T)); }
+
+ //! Returns number of instances
+ const count_type& count()const { return refcount; }
+
+ //! Returns true if there is only one instance of the object
+ bool unique()const { return refcount.unique(); }
+
+ //! Returns a constant handle to our object
+ smart_ptr<const value_type> constant() { return *this; }
+
+ reference operator*()const { assert(obj); return *obj; }
+
+ pointer operator->()const { assert(obj); return obj; }
+
+
+ operator smart_ptr<const value_type>()const
+ { return smart_ptr<const value_type>(static_cast<const_pointer>(obj)); }
+
+ //! static_cast<> wrapper
+ template <class U> static
+ smart_ptr<T> cast_static(const smart_ptr<U> &x)
+ { if(!x)return NULL; return smart_ptr<T>(static_cast<T*>(x.get()),x.refcount); }
+
+ //! dynamic_cast<> wrapper
+ template <class U> static
+ smart_ptr<T> cast_dynamic(const smart_ptr<U> &x)
+ { if(!x)return 0; return smart_ptr<T>(dynamic_cast<T*>(x.get()),x.refcount); }
+
+ //! const_cast<> wrapper
+ template <class U> static
+ smart_ptr<T> cast_const(const smart_ptr<U> &x)
+ { if(!x)return 0; return smart_ptr<T>(const_cast<T*>(x.get()),x.refcount); }
+
+ pointer get()const { return obj; }
+
+ //! More explicit bool cast
+ operator bool()const { return obj!=0; }
+
+ bool operator!()const { return !obj; }
+
+ //! Overloaded cast operator -- useful for implicit casts
+ template <class U>
+ operator smart_ptr<U>()
+ {
+ // This next line should provide a syntax check
+ // to make sure that this cast makes sense.
+ // If it doesn't, this should have a compiler error.
+ // Otherwise, it should get optimized right out
+ // of the code.
+ //(U*)obj;
+
+ return *reinterpret_cast<smart_ptr<U>*>(this);
+ }
+
+}; // END of template class smart_ptr
+
+// ========================================================================
+/*! \class loose_smart_ptr _smart_ptr.h ETL/smart_ptr
+** \brief Loose Object Smart Pointer
+** \see smart_ptr
+** \writeme
+*/
+template <class T>
+class loose_smart_ptr
+{
+public:
+
+ typedef T value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef int count_type;
+ typedef int size_type;
+
+private:
+ value_type *obj; //!< \internal Pointer to object
+ weak_reference_counter refcount; //!< \internal Pointer to object's reference counter
+
+public:
+
+ //! Default constructor - empty smart_ptr
+ loose_smart_ptr():obj(0),refcount(0) {}
+
+ //! Default copy constructor
+ loose_smart_ptr(const loose_smart_ptr<value_type> &x):obj(x.get()),refcount(x.refcount) { }
+
+ loose_smart_ptr(const smart_ptr<value_type> &x):obj(x.get()),refcount(x.refcount) { }
+
+ void reset() { obj=0,refcount=0; }
+
+ operator smart_ptr<value_type>()
+ {
+ return smart_ptr<value_type>(static_cast<pointer>(obj),refcount);
+ }
+
+ operator smart_ptr<const value_type>()
+ {
+ return smart_ptr<const value_type>(static_cast<const_pointer>(obj),refcount);
+ }
+
+ //! Returns number of instances
+ const count_type& count()const { return refcount; }
+
+ bool unique()const { return refcount.unique(); }
+
+ reference operator*()const { assert(obj); return *obj; }
+
+ pointer operator->()const { assert(obj); return obj; }
+
+ pointer get()const { return obj; }
+
+ bool operator!()const { return !obj; }
+};
+
+template <class T,class U> bool
+operator==(const smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
+ { return (lhs.get()==rhs.get()); }
+template <class T,class U> bool
+operator==(const loose_smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
+ { return (lhs.get()==rhs.get()); }
+template <class T,class U> bool
+operator==(const smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
+ { return (lhs.get()==rhs.get()); }
+template <class T,class U> bool
+operator==(const loose_smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
+ { return (lhs.get()==rhs.get()); }
+template <class T> bool
+operator==(const smart_ptr<T> &lhs,const T *rhs)
+ { return (lhs.get()==rhs); }
+template <class T> bool
+operator==(const loose_smart_ptr<T> &lhs,const T *rhs)
+ { return (lhs.get()==rhs); }
+template <class T> bool
+operator==(const T *lhs,const smart_ptr<T> &rhs)
+ { return (lhs==rhs.get()); }
+template <class T> bool
+operator==(const T *lhs,const loose_smart_ptr<T> &rhs)
+ { return (lhs==rhs.get()); }
+
+
+template <class T,class U> bool
+operator!=(const smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
+ { return (lhs.get()!=rhs.get()); }
+template <class T,class U> bool
+operator!=(const loose_smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
+ { return (lhs.get()!=rhs.get()); }
+template <class T,class U> bool
+operator!=(const smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
+ { return (lhs.get()!=rhs.get()); }
+template <class T,class U> bool
+operator!=(const loose_smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
+ { return (lhs.get()!=rhs.get()); }
+template <class T> bool
+operator!=(const smart_ptr<T> &lhs,const T *rhs)
+ { return (lhs.get()!=rhs); }
+template <class T> bool
+operator!=(const loose_smart_ptr<T> &lhs,const T *rhs)
+ { return (lhs.get()!=rhs); }
+template <class T> bool
+operator!=(const T *lhs,const smart_ptr<T> &rhs)
+ { return (lhs!=rhs.get()); }
+template <class T> bool
+operator!=(const T *lhs,const loose_smart_ptr<T> &rhs)
+ { return (lhs!=rhs.get()); }
+
+
+template <class T,class U> bool
+operator<(const smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
+ { return (lhs.get()<rhs.get()); }
+template <class T,class U> bool
+operator<(const loose_smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
+ { return (lhs.get()<rhs.get()); }
+template <class T,class U> bool
+operator<(const smart_ptr<T> &lhs,const loose_smart_ptr<U> &rhs)
+ { return (lhs.get()<rhs.get()); }
+template <class T,class U> bool
+operator<(const loose_smart_ptr<T> &lhs,const smart_ptr<U> &rhs)
+ { return (lhs.get()<rhs.get()); }
+template <class T> bool
+operator<(const smart_ptr<T> &lhs,const T *rhs)
+ { return (lhs.get()<rhs); }
+template <class T> bool
+operator<(const loose_smart_ptr<T> &lhs,const T *rhs)
+ { return (lhs.get()<rhs); }
+template <class T> bool
+operator<(const T *lhs,const smart_ptr<T> &rhs)
+ { return (lhs<rhs.get()); }
+template <class T> bool
+operator<(const T *lhs,const loose_smart_ptr<T> &rhs)
+ { return (lhs<rhs.get()); }
+
+_ETL_END_NAMESPACE
+
+/* === E N D =============================================================== */
+
+#endif