-////////////////////////////////////////////////////////////////////////////////\r
-\r
-// Author: Andy Rushton\r
-// Copyright: (c) Southampton University 1999-2004\r
-// (c) Andy Rushton 2004-2009\r
-// License: BSD License, see ../docs/license.html\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-namespace stlplus\r
-{\r
-\r
- ////////////////////////////////////////////////////////////////////////////////\r
- // internal holder data structure\r
- ////////////////////////////////////////////////////////////////////////////////\r
-\r
- template<typename T>\r
- class smart_ptr_holder\r
- {\r
- private:\r
- unsigned m_count;\r
- T* m_data;\r
-\r
- // make these private to disallow copying because the holder doesn't know how to copy\r
- smart_ptr_holder(const smart_ptr_holder& s) :\r
- m_count(0), m_data(0)\r
- {\r
- }\r
-\r
- smart_ptr_holder& operator=(const smart_ptr_holder& s)\r
- {\r
- return *this;\r
- }\r
-\r
- public:\r
- smart_ptr_holder(T* p = 0) :\r
- m_count(1), m_data(p)\r
- {\r
- }\r
-\r
- ~smart_ptr_holder(void)\r
- {\r
- clear();\r
- }\r
-\r
- unsigned count(void) const\r
- {\r
- return m_count;\r
- }\r
-\r
- void increment(void)\r
- {\r
- ++m_count;\r
- }\r
-\r
- bool decrement(void)\r
- {\r
- --m_count;\r
- return m_count == 0;\r
- }\r
-\r
- bool null(void)\r
- {\r
- return m_data == 0;\r
- }\r
-\r
- void clear(void)\r
- {\r
- if(m_data)\r
- delete m_data;\r
- m_data = 0;\r
- }\r
-\r
- void set(T* p = 0)\r
- {\r
- clear();\r
- m_data = p;\r
- }\r
-\r
- T*& pointer(void)\r
- {\r
- return m_data;\r
- }\r
-\r
- const T* pointer(void) const\r
- {\r
- return m_data;\r
- }\r
-\r
- T& value(void)\r
- {\r
- return *m_data;\r
- }\r
-\r
- const T& value(void) const\r
- {\r
- return *m_data;\r
- }\r
- };\r
-\r
- ////////////////////////////////////////////////////////////////////////////////\r
- // smart_ptr_base class\r
- ////////////////////////////////////////////////////////////////////////////////\r
-\r
- ////////////////////////////////////////////////////////////////////////////////\r
- // constructors, assignments and destructors\r
-\r
- // create a null pointer\r
- template <typename T, typename C>\r
- smart_ptr_base<T,C>::smart_ptr_base(void) :\r
- m_holder(new smart_ptr_holder<T>)\r
- {\r
- }\r
-\r
- // create a pointer containing a *copy* of the object pointer\r
- template <typename T, typename C>\r
- smart_ptr_base<T,C>::smart_ptr_base(const T& data) throw(illegal_copy) :\r
- m_holder(new smart_ptr_holder<T>)\r
- {\r
- m_holder->set(C()(data));\r
- }\r
-\r
- // create a pointer containing a dynamically created object\r
- // Note: the object must be allocated *by the user* with new\r
- // constructor form - must be called in the form smart_ptr<type> x(new type(args))\r
- template <typename T, typename C>\r
- smart_ptr_base<T,C>::smart_ptr_base(T* data) :\r
- m_holder(new smart_ptr_holder<T>)\r
- {\r
- m_holder->set(data);\r
- }\r
-\r
- // copy constructor implements counted referencing - no copy is made\r
- template <typename T, typename C>\r
- smart_ptr_base<T,C>::smart_ptr_base(const smart_ptr_base<T,C>& r) :\r
- m_holder(0)\r
- {\r
- m_holder = r.m_holder;\r
- m_holder->increment();\r
- }\r
-\r
- // assignment operator - required, else the output of GCC suffers segmentation faults\r
- template <typename T, typename C>\r
- smart_ptr_base<T,C>& smart_ptr_base<T,C>::operator=(const smart_ptr_base<T,C>& r) \r
- {\r
- alias(r);\r
- return *this;\r
- }\r
-\r
- // destructor decrements the reference count and delete only when the last reference is destroyed\r
- template <typename T, typename C>\r
- smart_ptr_base<T,C>::~smart_ptr_base(void)\r
- {\r
- if(m_holder->decrement())\r
- delete m_holder;\r
- }\r
-\r
- //////////////////////////////////////////////////////////////////////////////\r
- // logical tests to see if there is anything contained in the pointer since it can be null\r
-\r
- template <typename T, typename C>\r
- bool smart_ptr_base<T,C>::null(void) const\r
- {\r
- return m_holder->null();\r
- }\r
-\r
- template <typename T, typename C>\r
- bool smart_ptr_base<T,C>::present(void) const\r
- {\r
- return !m_holder->null();\r
- }\r
-\r
- template <typename T, typename C>\r
- bool smart_ptr_base<T,C>::operator!(void) const\r
- {\r
- return m_holder->null();\r
- }\r
-\r
- template <typename T, typename C>\r
- smart_ptr_base<T,C>::operator bool(void) const\r
- {\r
- return !m_holder->null();\r
- }\r
-\r
- //////////////////////////////////////////////////////////////////////////////\r
- // dereference operators and functions\r
-\r
- template <typename T, typename C>\r
- T& smart_ptr_base<T,C>::operator*(void) throw(null_dereference)\r
- {\r
- if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator*");\r
- return m_holder->value();\r
- }\r
-\r
- template <typename T, typename C>\r
- const T& smart_ptr_base<T,C>::operator*(void) const throw(null_dereference)\r
- {\r
- if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator*");\r
- return m_holder->value();\r
- }\r
-\r
- template <typename T, typename C>\r
- T* smart_ptr_base<T,C>::operator->(void) throw(null_dereference)\r
- {\r
- if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator->");\r
- return m_holder->pointer();\r
- }\r
-\r
- template <typename T, typename C>\r
- const T* smart_ptr_base<T,C>::operator->(void) const throw(null_dereference)\r
- {\r
- if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator->");\r
- return m_holder->pointer();\r
- }\r
-\r
- //////////////////////////////////////////////////////////////////////////////\r
- // explicit function forms of the above assignment dereference operators\r
-\r
- template <typename T, typename C>\r
- void smart_ptr_base<T,C>::set_value(const T& data) throw(illegal_copy)\r
- {\r
- m_holder->set(C()(data));\r
- }\r
-\r
- template <typename T, typename C>\r
- T& smart_ptr_base<T,C>::value(void) throw(null_dereference)\r
- {\r
- if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::value");\r
- return m_holder->value();\r
- }\r
-\r
- template <typename T, typename C>\r
- const T& smart_ptr_base<T,C>::value(void) const throw(null_dereference)\r
- {\r
- if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::value");\r
- return m_holder->value();\r
- }\r
-\r
- template <typename T, typename C>\r
- void smart_ptr_base<T,C>::set(T* data)\r
- {\r
- m_holder->set(data);\r
- }\r
-\r
- template <typename T, typename C>\r
- T* smart_ptr_base<T,C>::pointer(void)\r
- {\r
- return m_holder->pointer();\r
- }\r
-\r
- template <typename T, typename C>\r
- const T* smart_ptr_base<T,C>::pointer(void) const\r
- {\r
- return m_holder->pointer();\r
- }\r
-\r
- ////////////////////////////////////////////////////////////////////////////////\r
- // functions to manage counted referencing\r
-\r
- // make this an alias of the passed object\r
- template <typename T, typename C>\r
- void smart_ptr_base<T,C>::alias(const smart_ptr_base<T,C>& r)\r
- {\r
- _make_alias(r.m_holder);\r
- }\r
-\r
- template <typename T, typename C>\r
- bool smart_ptr_base<T,C>::aliases(const smart_ptr_base<T,C>& r) const\r
- {\r
- return m_holder == r.m_holder;\r
- }\r
-\r
- template <typename T, typename C>\r
- unsigned smart_ptr_base<T,C>::alias_count(void) const\r
- {\r
- return m_holder->count();\r
- }\r
-\r
- template <typename T, typename C>\r
- void smart_ptr_base<T,C>::clear(void)\r
- {\r
- m_holder->clear();\r
- }\r
-\r
- template <typename T, typename C>\r
- void smart_ptr_base<T,C>::clear_unique(void)\r
- {\r
- if (m_holder->count() == 1)\r
- m_holder->clear();\r
- else\r
- {\r
- m_holder->decrement();\r
- m_holder = 0;\r
- m_holder = new smart_ptr_holder<T>;\r
- }\r
- }\r
-\r
- template <typename T, typename C>\r
- void smart_ptr_base<T,C>::make_unique(void) throw(illegal_copy)\r
- {\r
- if (m_holder->count() > 1)\r
- {\r
- smart_ptr_holder<T>* old_holder = m_holder;\r
- m_holder->decrement();\r
- m_holder = 0;\r
- m_holder = new smart_ptr_holder<T>;\r
- if (old_holder->pointer())\r
- m_holder->set(C()(old_holder->value()));\r
- }\r
- }\r
-\r
- template <typename T, typename C>\r
- void smart_ptr_base<T,C>::copy(const smart_ptr_base<T,C>& data) throw(illegal_copy)\r
- {\r
- alias(data);\r
- make_unique();\r
- }\r
-\r
- // internal function for distinguishing unique smart_ptr objects\r
- // used for example in persistence routines\r
-\r
- template <typename T, typename C>\r
- smart_ptr_holder<T>* smart_ptr_base<T,C>::_handle(void) const\r
- {\r
- return m_holder;\r
- }\r
-\r
- template <typename T, typename C>\r
- void smart_ptr_base<T,C>::_make_alias(smart_ptr_holder<T>* r_holder)\r
- {\r
- // make it alias-copy safe - this means that I don't try to do the\r
- // assignment if r is either the same object or an alias of it\r
- if (m_holder != r_holder)\r
- {\r
- if (m_holder->decrement())\r
- delete m_holder;\r
- m_holder = r_holder;\r
- m_holder->increment();\r
- }\r
- }\r
-\r
- ////////////////////////////////////////////////////////////////////////////////\r
-\r
-} // end namespace stlplus\r
-\r
+////////////////////////////////////////////////////////////////////////////////
+
+// Author: Andy Rushton
+// Copyright: (c) Southampton University 1999-2004
+// (c) Andy Rushton 2004-2009
+// License: BSD License, see ../docs/license.html
+
+////////////////////////////////////////////////////////////////////////////////
+
+namespace stlplus
+{
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // internal holder data structure
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename T>
+ class smart_ptr_holder
+ {
+ private:
+ unsigned m_count;
+ T* m_data;
+
+ // make these private to disallow copying because the holder doesn't know how to copy
+ smart_ptr_holder(const smart_ptr_holder& s) :
+ m_count(0), m_data(0)
+ {
+ }
+
+ smart_ptr_holder& operator=(const smart_ptr_holder& s)
+ {
+ return *this;
+ }
+
+ public:
+ smart_ptr_holder(T* p = 0) :
+ m_count(1), m_data(p)
+ {
+ }
+
+ ~smart_ptr_holder(void)
+ {
+ clear();
+ }
+
+ unsigned count(void) const
+ {
+ return m_count;
+ }
+
+ void increment(void)
+ {
+ ++m_count;
+ }
+
+ bool decrement(void)
+ {
+ --m_count;
+ return m_count == 0;
+ }
+
+ bool null(void)
+ {
+ return m_data == 0;
+ }
+
+ void clear(void)
+ {
+ if(m_data)
+ delete m_data;
+ m_data = 0;
+ }
+
+ void set(T* p = 0)
+ {
+ clear();
+ m_data = p;
+ }
+
+ T*& pointer(void)
+ {
+ return m_data;
+ }
+
+ const T* pointer(void) const
+ {
+ return m_data;
+ }
+
+ T& value(void)
+ {
+ return *m_data;
+ }
+
+ const T& value(void) const
+ {
+ return *m_data;
+ }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // smart_ptr_base class
+ ////////////////////////////////////////////////////////////////////////////////
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // constructors, assignments and destructors
+
+ // create a null pointer
+ template <typename T, typename C>
+ smart_ptr_base<T,C>::smart_ptr_base(void) :
+ m_holder(new smart_ptr_holder<T>)
+ {
+ }
+
+ // create a pointer containing a *copy* of the object pointer
+ template <typename T, typename C>
+ smart_ptr_base<T,C>::smart_ptr_base(const T& data) throw(illegal_copy) :
+ m_holder(new smart_ptr_holder<T>)
+ {
+ m_holder->set(C()(data));
+ }
+
+ // create a pointer containing a dynamically created object
+ // Note: the object must be allocated *by the user* with new
+ // constructor form - must be called in the form smart_ptr<type> x(new type(args))
+ template <typename T, typename C>
+ smart_ptr_base<T,C>::smart_ptr_base(T* data) :
+ m_holder(new smart_ptr_holder<T>)
+ {
+ m_holder->set(data);
+ }
+
+ // copy constructor implements counted referencing - no copy is made
+ template <typename T, typename C>
+ smart_ptr_base<T,C>::smart_ptr_base(const smart_ptr_base<T,C>& r) :
+ m_holder(0)
+ {
+ m_holder = r.m_holder;
+ m_holder->increment();
+ }
+
+ // assignment operator - required, else the output of GCC suffers segmentation faults
+ template <typename T, typename C>
+ smart_ptr_base<T,C>& smart_ptr_base<T,C>::operator=(const smart_ptr_base<T,C>& r)
+ {
+ alias(r);
+ return *this;
+ }
+
+ // destructor decrements the reference count and delete only when the last reference is destroyed
+ template <typename T, typename C>
+ smart_ptr_base<T,C>::~smart_ptr_base(void)
+ {
+ if(m_holder->decrement())
+ delete m_holder;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // logical tests to see if there is anything contained in the pointer since it can be null
+
+ template <typename T, typename C>
+ bool smart_ptr_base<T,C>::null(void) const
+ {
+ return m_holder->null();
+ }
+
+ template <typename T, typename C>
+ bool smart_ptr_base<T,C>::present(void) const
+ {
+ return !m_holder->null();
+ }
+
+ template <typename T, typename C>
+ bool smart_ptr_base<T,C>::operator!(void) const
+ {
+ return m_holder->null();
+ }
+
+ template <typename T, typename C>
+ smart_ptr_base<T,C>::operator bool(void) const
+ {
+ return !m_holder->null();
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // dereference operators and functions
+
+ template <typename T, typename C>
+ T& smart_ptr_base<T,C>::operator*(void) throw(null_dereference)
+ {
+ if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator*");
+ return m_holder->value();
+ }
+
+ template <typename T, typename C>
+ const T& smart_ptr_base<T,C>::operator*(void) const throw(null_dereference)
+ {
+ if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator*");
+ return m_holder->value();
+ }
+
+ template <typename T, typename C>
+ T* smart_ptr_base<T,C>::operator->(void) throw(null_dereference)
+ {
+ if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator->");
+ return m_holder->pointer();
+ }
+
+ template <typename T, typename C>
+ const T* smart_ptr_base<T,C>::operator->(void) const throw(null_dereference)
+ {
+ if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator->");
+ return m_holder->pointer();
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // explicit function forms of the above assignment dereference operators
+
+ template <typename T, typename C>
+ void smart_ptr_base<T,C>::set_value(const T& data) throw(illegal_copy)
+ {
+ m_holder->set(C()(data));
+ }
+
+ template <typename T, typename C>
+ T& smart_ptr_base<T,C>::value(void) throw(null_dereference)
+ {
+ if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::value");
+ return m_holder->value();
+ }
+
+ template <typename T, typename C>
+ const T& smart_ptr_base<T,C>::value(void) const throw(null_dereference)
+ {
+ if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::value");
+ return m_holder->value();
+ }
+
+ template <typename T, typename C>
+ void smart_ptr_base<T,C>::set(T* data)
+ {
+ m_holder->set(data);
+ }
+
+ template <typename T, typename C>
+ T* smart_ptr_base<T,C>::pointer(void)
+ {
+ return m_holder->pointer();
+ }
+
+ template <typename T, typename C>
+ const T* smart_ptr_base<T,C>::pointer(void) const
+ {
+ return m_holder->pointer();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // functions to manage counted referencing
+
+ // make this an alias of the passed object
+ template <typename T, typename C>
+ void smart_ptr_base<T,C>::alias(const smart_ptr_base<T,C>& r)
+ {
+ _make_alias(r.m_holder);
+ }
+
+ template <typename T, typename C>
+ bool smart_ptr_base<T,C>::aliases(const smart_ptr_base<T,C>& r) const
+ {
+ return m_holder == r.m_holder;
+ }
+
+ template <typename T, typename C>
+ unsigned smart_ptr_base<T,C>::alias_count(void) const
+ {
+ return m_holder->count();
+ }
+
+ template <typename T, typename C>
+ void smart_ptr_base<T,C>::clear(void)
+ {
+ m_holder->clear();
+ }
+
+ template <typename T, typename C>
+ void smart_ptr_base<T,C>::clear_unique(void)
+ {
+ if (m_holder->count() == 1)
+ m_holder->clear();
+ else
+ {
+ m_holder->decrement();
+ m_holder = 0;
+ m_holder = new smart_ptr_holder<T>;
+ }
+ }
+
+ template <typename T, typename C>
+ void smart_ptr_base<T,C>::make_unique(void) throw(illegal_copy)
+ {
+ if (m_holder->count() > 1)
+ {
+ smart_ptr_holder<T>* old_holder = m_holder;
+ m_holder->decrement();
+ m_holder = 0;
+ m_holder = new smart_ptr_holder<T>;
+ if (old_holder->pointer())
+ m_holder->set(C()(old_holder->value()));
+ }
+ }
+
+ template <typename T, typename C>
+ void smart_ptr_base<T,C>::copy(const smart_ptr_base<T,C>& data) throw(illegal_copy)
+ {
+ alias(data);
+ make_unique();
+ }
+
+ // internal function for distinguishing unique smart_ptr objects
+ // used for example in persistence routines
+
+ template <typename T, typename C>
+ smart_ptr_holder<T>* smart_ptr_base<T,C>::_handle(void) const
+ {
+ return m_holder;
+ }
+
+ template <typename T, typename C>
+ void smart_ptr_base<T,C>::_make_alias(smart_ptr_holder<T>* r_holder)
+ {
+ // make it alias-copy safe - this means that I don't try to do the
+ // assignment if r is either the same object or an alias of it
+ if (m_holder != r_holder)
+ {
+ if (m_holder->decrement())
+ delete m_holder;
+ m_holder = r_holder;
+ m_holder->increment();
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+} // end namespace stlplus
+