X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2Fstlplus%2Fcontainers%2Fsimple_ptr.hpp;h=72d1db7e16d0bf15efed1cd6c9dba1103fd1efb3;hp=08fff036eb91612865a8207b777e57deaa91e303;hb=5846afb00833cc72fe72422ca896d2387c712cb4;hpb=a97500609dc3c1b11f9786d32bc458eb00de4c36 diff --git a/src/stlplus/containers/simple_ptr.hpp b/src/stlplus/containers/simple_ptr.hpp index 08fff03..72d1db7 100644 --- a/src/stlplus/containers/simple_ptr.hpp +++ b/src/stlplus/containers/simple_ptr.hpp @@ -1,264 +1,264 @@ -#ifndef STLPLUS_SIMPLE_PTR -#define STLPLUS_SIMPLE_PTR -//////////////////////////////////////////////////////////////////////////////// - -// Author: Daniel Milton, Andy Rushton -// Copyright: (c) Southampton University 1999-2004 -// (c) Daniel Milton, Andy Rushton 2004-2009 -// License: BSD License, see ../docs/license.html - -// A smart pointer is a memory-managing pointer to an object. If you like, it -// is a zero-dimensional container. - -// Assignment of smart pointers result in multiple aliases of the same object. -// The term alias is used to differentiate from conventional pointers because -// the semantics are different. - -// Aliases can be turned into copies if the pointed-to class supports copying. - -// These simple_ptr classes from DJDM have slightly different semantics than -// the smart_ptr classes of AJR. There are no cross-pointer side effects -// that occur when the pointer is cleared. The clear() function is effectively -// equivalent to the clear_unique() function of the smart_ptr. The only way -// that a "referenced" object will be deleted is if all simple_ptr's that -// reference the object are cleared (by deletion, manual clearing or reassignment). - -// Also, the simple pointer cannot contain a reference to a shared null pointer -// (which occurs as a side-effect of clearing a multiply referenced object in -// the smart_ptr classes). Which means that if you have a null simple_ptr, then -// the assignment of any other null simple_ptr will NOT reassign the reference of -// any other simple_ptr. Hence, the simple_ptr class acts a little more like a -// normal pointer (with fewer side effects), with the added bonus of containment. - -// Due to the way that the simple_ptr contains the data, it also allows the -// addition of various casting functions, while still keeping the managed data -// containment functionality of the underlying object. This means that you can -// have two simple_ptr's of different template types, both pointing to the same -// data (if the differing template types are derivatives of each other). - -// The base class is simple_ptr_base which defines the common interface. Then -// there are three subclasses which have the same interface but different copy -// semantics: - -// - simple_ptr for simple types and classes which have copy constructors -// - simple_ptr_clone for polymorphic class hierarchies which are copied using a clone method -// - simple_ptr_nocopy for any class that cannot or should not be copied - -//////////////////////////////////////////////////////////////////////////////// -#include "containers_fixes.hpp" -#include "exceptions.hpp" -#include "copy_functors.hpp" -#include -#include - -namespace stlplus -{ - - //////////////////////////////////////////////////////////////////////////////// - // Base class - //////////////////////////////////////////////////////////////////////////////// - - template - class simple_ptr_base - { - public: - ////////////////////////////////////////////////////////////////////////////// - // member type definitions - - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - typedef C value_copy; - - ////////////////////////////////////////////////////////////////////////////// - // constructors and destructors - - // create a null pointer - simple_ptr_base(void); - - // create a pointer containing a *copy* of the object using the template parameter C - // this copy is taken because the pointer class maintains a dynamically allocated object - // and the T& may not be (usually is not) dynamically allocated - explicit simple_ptr_base(const T& data) throw(illegal_copy); - - // 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_base x(new type(args)) - explicit simple_ptr_base(T* data); - - // copy constructor implements aliasing so no copy is made - // note that the copy constructor should NOT be explicit, as this breaks - // the returning of pointer objects from functions (at least within GCC 4.4) - simple_ptr_base(const simple_ptr_base& r); - - // assignment operator - required, else the output of GCC suffers segmentation faults - simple_ptr_base& operator=(const simple_ptr_base& r); - - // destructor decrements the reference count and delete only when the last reference is destroyed - ~simple_ptr_base(void); - - ////////////////////////////////////////////////////////////////////////////// - // logical tests to see if there is anything contained in the pointer since it can be null - - // there are two forms:explicit and implicit - // implicit: if(!r) or if(r) - // explicit: if(r.null()) or if(r.present()) - operator bool(void) const; - bool operator!(void) const; - bool present(void) const; - bool null(void) const; - - ////////////////////////////////////////////////////////////////////////////// - // dereference operators and functions - - // dereference the smart pointer to get the object - use in the form *p1 - T& operator*(void) throw(null_dereference); - const T& operator*(void) const throw(null_dereference); - - // used as a prefix to a member access to the contained object e.g. p1->print() calls T::print() - T* operator->(void) throw(null_dereference); - const T* operator->(void) const throw(null_dereference); - - ////////////////////////////////////////////////////////////////////////////// - // explicit function forms of the above assignment and dereference operators - - // set the value - note that this does a copy using the C template parameter - void set_value(const T& data) throw(illegal_copy); - // get the value - T& value(void) throw(null_dereference); - const T& value(void) const throw(null_dereference); - - // set the pointer - // deletes the previous pointer and adopts the passed pointer instead - // Note: the object must be allocated *by the user* with new - // Warning: it is very easy to break the memory management with this operation - void set(T* data = 0); - // get the pointer - T* pointer(void); - const T* pointer(void) const; - - ////////////////////////////////////////////////////////////////////////////// - // functions to manage aliases - - // make this an alias of the passed object - void alias(const simple_ptr_base&); - - // test whether two pointers point to the same object(known as aliasing the object) - // used in the form if(a.aliases(b)) - bool aliases(const simple_ptr_base&) const; - - // find the number of aliases - used when you need to know whether an - // object is still referred to from elsewhere (rare!) - unsigned alias_count(void) const; - - // clear the reference to the object, but only delete the object if there are no - // other references to that object. Hence, this does not affect other pointers - // that are pointing to the same object. - void clear(void); - - // This is just an alias of the clear() function, provided for completeness of - // the interface when acting as a replacement for the smart_ptr classes - void clear_unique(void); - - ////////////////////////////////////////////////////////////////////////////// - // functions that involve copying - - // these functions use the copy functor passed as the template parameter C - // to copy the object with the right copy semantics. If the copy functor - // is no_copy, an exception will be thrown. - - // make this pointer unique with respect to any other references to the same object - // if this pointer is already unique, it does nothing - otherwise it copies the object - void make_unique(void) throw(illegal_copy); - - // make this pointer a unique copy of the parameter - // useful for expressions like p1.copy(p2) which makes p1 a pointer to a unique copy of the contents of p2 - void copy(const simple_ptr_base&) throw(illegal_copy); - - ////////////////////////////////////////////////////////////////////////////// - // functions that involve casting - -#ifdef STLPLUS_MEMBER_TEMPLATES - - // dynamic cast of underlying pointer to a derived/parent - template simple_ptr_base dyn_cast(void) const; - - // static cast of underlying pointer to a derived/parent - template simple_ptr_base stat_cast(void) const; - - // cast of underlying pointer to a base - while keeping the same ref-counted object - template simple_ptr_base cast(void) const; - -#endif - - ////////////////////////////////////////////////////////////////////////////// - - protected: - T* m_pointer; - unsigned* m_count; - - public: - // internal use only - had to make them public because they need to be - // accessed by routines that could not be made friends - // can't have a handle due to the way the simple pointer stores it's data - // in separate counter and pointer objects - unsigned* _count(void) const; - T* _pointer(void) const; - void _make_alias(T* pointer, unsigned* count); - - private: - void increment(void); - bool decrement(void); - }; - - //////////////////////////////////////////////////////////////////////////////// - // simple_ptr for simple types and classes which have copy constructors - - template - class simple_ptr : public simple_ptr_base > - { - public: - simple_ptr(void) {} - explicit simple_ptr(const T& data) : simple_ptr_base >(data) {} - explicit simple_ptr(T* data) : simple_ptr_base >(data) {} - simple_ptr& operator=(const T& data) {set_value(data); return *this;} - simple_ptr& operator=(T* data) {set(data); return *this;} - ~simple_ptr(void) {} - }; - - //////////////////////////////////////////////////////////////////////////////// - // smart_ptr_clone for polymorphic class hierarchies which have a clone method - - template - class simple_ptr_clone : public simple_ptr_base > - { - public: - simple_ptr_clone(void) {} - explicit simple_ptr_clone(const T& data) : simple_ptr_base >(data) {} - explicit simple_ptr_clone(T* data) : simple_ptr_base >(data) {} - simple_ptr_clone& operator=(const T& data) {set_value(data); return *this;} - simple_ptr_clone& operator=(T* data) {set(data); return *this;} - ~simple_ptr_clone(void) {} - }; - - //////////////////////////////////////////////////////////////////////////////// - // smart_ptr_nocopy for any class that cannot or should not be copied - - template - class simple_ptr_nocopy : public simple_ptr_base > - { - public: - simple_ptr_nocopy(void) {} - explicit simple_ptr_nocopy(const T& data) : simple_ptr_base >(data) {} - explicit simple_ptr_nocopy(T* data) : simple_ptr_base >(data) {} - simple_ptr_nocopy& operator=(const T& data) {set_value(data); return *this;} - simple_ptr_nocopy& operator=(T* data) {set(data); return *this;} - ~simple_ptr_nocopy(void) {} - }; - - //////////////////////////////////////////////////////////////////////////////// - -} // end namespace stlplus - -#include "simple_ptr.tpp" -#endif +#ifndef STLPLUS_SIMPLE_PTR +#define STLPLUS_SIMPLE_PTR +//////////////////////////////////////////////////////////////////////////////// + +// Author: Daniel Milton, Andy Rushton +// Copyright: (c) Southampton University 1999-2004 +// (c) Daniel Milton, Andy Rushton 2004-2009 +// License: BSD License, see ../docs/license.html + +// A smart pointer is a memory-managing pointer to an object. If you like, it +// is a zero-dimensional container. + +// Assignment of smart pointers result in multiple aliases of the same object. +// The term alias is used to differentiate from conventional pointers because +// the semantics are different. + +// Aliases can be turned into copies if the pointed-to class supports copying. + +// These simple_ptr classes from DJDM have slightly different semantics than +// the smart_ptr classes of AJR. There are no cross-pointer side effects +// that occur when the pointer is cleared. The clear() function is effectively +// equivalent to the clear_unique() function of the smart_ptr. The only way +// that a "referenced" object will be deleted is if all simple_ptr's that +// reference the object are cleared (by deletion, manual clearing or reassignment). + +// Also, the simple pointer cannot contain a reference to a shared null pointer +// (which occurs as a side-effect of clearing a multiply referenced object in +// the smart_ptr classes). Which means that if you have a null simple_ptr, then +// the assignment of any other null simple_ptr will NOT reassign the reference of +// any other simple_ptr. Hence, the simple_ptr class acts a little more like a +// normal pointer (with fewer side effects), with the added bonus of containment. + +// Due to the way that the simple_ptr contains the data, it also allows the +// addition of various casting functions, while still keeping the managed data +// containment functionality of the underlying object. This means that you can +// have two simple_ptr's of different template types, both pointing to the same +// data (if the differing template types are derivatives of each other). + +// The base class is simple_ptr_base which defines the common interface. Then +// there are three subclasses which have the same interface but different copy +// semantics: + +// - simple_ptr for simple types and classes which have copy constructors +// - simple_ptr_clone for polymorphic class hierarchies which are copied using a clone method +// - simple_ptr_nocopy for any class that cannot or should not be copied + +//////////////////////////////////////////////////////////////////////////////// +#include "containers_fixes.hpp" +#include "exceptions.hpp" +#include "copy_functors.hpp" +#include +#include + +namespace stlplus +{ + + //////////////////////////////////////////////////////////////////////////////// + // Base class + //////////////////////////////////////////////////////////////////////////////// + + template + class simple_ptr_base + { + public: + ////////////////////////////////////////////////////////////////////////////// + // member type definitions + + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + typedef C value_copy; + + ////////////////////////////////////////////////////////////////////////////// + // constructors and destructors + + // create a null pointer + simple_ptr_base(void); + + // create a pointer containing a *copy* of the object using the template parameter C + // this copy is taken because the pointer class maintains a dynamically allocated object + // and the T& may not be (usually is not) dynamically allocated + explicit simple_ptr_base(const T& data) throw(illegal_copy); + + // 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_base x(new type(args)) + explicit simple_ptr_base(T* data); + + // copy constructor implements aliasing so no copy is made + // note that the copy constructor should NOT be explicit, as this breaks + // the returning of pointer objects from functions (at least within GCC 4.4) + simple_ptr_base(const simple_ptr_base& r); + + // assignment operator - required, else the output of GCC suffers segmentation faults + simple_ptr_base& operator=(const simple_ptr_base& r); + + // destructor decrements the reference count and delete only when the last reference is destroyed + ~simple_ptr_base(void); + + ////////////////////////////////////////////////////////////////////////////// + // logical tests to see if there is anything contained in the pointer since it can be null + + // there are two forms:explicit and implicit + // implicit: if(!r) or if(r) + // explicit: if(r.null()) or if(r.present()) + operator bool(void) const; + bool operator!(void) const; + bool present(void) const; + bool null(void) const; + + ////////////////////////////////////////////////////////////////////////////// + // dereference operators and functions + + // dereference the smart pointer to get the object - use in the form *p1 + T& operator*(void) throw(null_dereference); + const T& operator*(void) const throw(null_dereference); + + // used as a prefix to a member access to the contained object e.g. p1->print() calls T::print() + T* operator->(void) throw(null_dereference); + const T* operator->(void) const throw(null_dereference); + + ////////////////////////////////////////////////////////////////////////////// + // explicit function forms of the above assignment and dereference operators + + // set the value - note that this does a copy using the C template parameter + void set_value(const T& data) throw(illegal_copy); + // get the value + T& value(void) throw(null_dereference); + const T& value(void) const throw(null_dereference); + + // set the pointer + // deletes the previous pointer and adopts the passed pointer instead + // Note: the object must be allocated *by the user* with new + // Warning: it is very easy to break the memory management with this operation + void set(T* data = 0); + // get the pointer + T* pointer(void); + const T* pointer(void) const; + + ////////////////////////////////////////////////////////////////////////////// + // functions to manage aliases + + // make this an alias of the passed object + void alias(const simple_ptr_base&); + + // test whether two pointers point to the same object(known as aliasing the object) + // used in the form if(a.aliases(b)) + bool aliases(const simple_ptr_base&) const; + + // find the number of aliases - used when you need to know whether an + // object is still referred to from elsewhere (rare!) + unsigned alias_count(void) const; + + // clear the reference to the object, but only delete the object if there are no + // other references to that object. Hence, this does not affect other pointers + // that are pointing to the same object. + void clear(void); + + // This is just an alias of the clear() function, provided for completeness of + // the interface when acting as a replacement for the smart_ptr classes + void clear_unique(void); + + ////////////////////////////////////////////////////////////////////////////// + // functions that involve copying + + // these functions use the copy functor passed as the template parameter C + // to copy the object with the right copy semantics. If the copy functor + // is no_copy, an exception will be thrown. + + // make this pointer unique with respect to any other references to the same object + // if this pointer is already unique, it does nothing - otherwise it copies the object + void make_unique(void) throw(illegal_copy); + + // make this pointer a unique copy of the parameter + // useful for expressions like p1.copy(p2) which makes p1 a pointer to a unique copy of the contents of p2 + void copy(const simple_ptr_base&) throw(illegal_copy); + + ////////////////////////////////////////////////////////////////////////////// + // functions that involve casting + +#ifdef STLPLUS_MEMBER_TEMPLATES + + // dynamic cast of underlying pointer to a derived/parent + template simple_ptr_base dyn_cast(void) const; + + // static cast of underlying pointer to a derived/parent + template simple_ptr_base stat_cast(void) const; + + // cast of underlying pointer to a base - while keeping the same ref-counted object + template simple_ptr_base cast(void) const; + +#endif + + ////////////////////////////////////////////////////////////////////////////// + + protected: + T* m_pointer; + unsigned* m_count; + + public: + // internal use only - had to make them public because they need to be + // accessed by routines that could not be made friends + // can't have a handle due to the way the simple pointer stores it's data + // in separate counter and pointer objects + unsigned* _count(void) const; + T* _pointer(void) const; + void _make_alias(T* pointer, unsigned* count); + + private: + void increment(void); + bool decrement(void); + }; + + //////////////////////////////////////////////////////////////////////////////// + // simple_ptr for simple types and classes which have copy constructors + + template + class simple_ptr : public simple_ptr_base > + { + public: + simple_ptr(void) {} + explicit simple_ptr(const T& data) : simple_ptr_base >(data) {} + explicit simple_ptr(T* data) : simple_ptr_base >(data) {} + simple_ptr& operator=(const T& data) {set_value(data); return *this;} + simple_ptr& operator=(T* data) {set(data); return *this;} + ~simple_ptr(void) {} + }; + + //////////////////////////////////////////////////////////////////////////////// + // smart_ptr_clone for polymorphic class hierarchies which have a clone method + + template + class simple_ptr_clone : public simple_ptr_base > + { + public: + simple_ptr_clone(void) {} + explicit simple_ptr_clone(const T& data) : simple_ptr_base >(data) {} + explicit simple_ptr_clone(T* data) : simple_ptr_base >(data) {} + simple_ptr_clone& operator=(const T& data) {set_value(data); return *this;} + simple_ptr_clone& operator=(T* data) {set(data); return *this;} + ~simple_ptr_clone(void) {} + }; + + //////////////////////////////////////////////////////////////////////////////// + // smart_ptr_nocopy for any class that cannot or should not be copied + + template + class simple_ptr_nocopy : public simple_ptr_base > + { + public: + simple_ptr_nocopy(void) {} + explicit simple_ptr_nocopy(const T& data) : simple_ptr_base >(data) {} + explicit simple_ptr_nocopy(T* data) : simple_ptr_base >(data) {} + simple_ptr_nocopy& operator=(const T& data) {set_value(data); return *this;} + simple_ptr_nocopy& operator=(T* data) {set(data); return *this;} + ~simple_ptr_nocopy(void) {} + }; + + //////////////////////////////////////////////////////////////////////////////// + +} // end namespace stlplus + +#include "simple_ptr.tpp" +#endif