smart_ptr.hpp

    1: #ifndef SMART_PTR_HPP
    2: #define SMART_PTR_HPP
    3: /*------------------------------------------------------------------------------
    4: 
    5:   Author:    Andy Rushton and Daniel Milton
    6:   Copyright: (c) Southampton University 1999-2004
    7:              (c) Andy Rushton           2004-2009
    8:   License:   BSD License, see ../docs/license.html
    9: 
   10:   Dan Milton: three simple pointer containers with single level access:
   11:     - simple_ptr for simple types and classes
   12:     - simple_ptr_clone for polymorphic class hierarchies
   13:     - simple_ptr_nocopy for any class that cannot or should no be copied
   14: 
   15:   Andy Rushton: three smart pointer containers with two-layer access:
   16:     - smart_ptr for simple types and classes
   17:     - smart_ptr_clone for polymorphic class hierarchies
   18:     - smart_ptr_nocopy for any class that cannot or should no be copied
   19: 
   20:   ------------------------------------------------------------------------------*/
   21: #include "os_fixes.hpp"
   22: #include "exceptions.hpp"
   23: #include "persistent.hpp"
   24: #include "textio.hpp"
   25: #include <map>
   26: #include <string>
   27: 
   28: ////////////////////////////////////////////////////////////////////////////////
   29: ////////////////////////////////////////////////////////////////////////////////
   30: // Simple pointer class
   31: ////////////////////////////////////////////////////////////////////////////////
   32: ////////////////////////////////////////////////////////////////////////////////
   33: 
   34: template<typename T>
   35: class simple_ptr
   36: {
   37: public:
   38:   //////////////////////////////////////////////////////////////////////////////
   39:   // member type definitions
   40: 
   41:   typedef T value_type;
   42:   typedef T& reference;
   43:   typedef const T& const_reference;
   44: 
   45:   //////////////////////////////////////////////////////////////////////////////
   46:   // constructors, assignments and destructors
   47: 
   48:   // create a null pointer
   49:   simple_ptr(void);
   50: 
   51:   // create a pointer containing a *copy* of the object
   52:   // this copy is taken because the pointer class maintains a dynamically allocated object 
   53:   // and the T& may not be (usually is not) dynamically allocated
   54:   // constructor form
   55:   simple_ptr(const T& data);
   56:   // assignment form for an already-constructed smart-pointer
   57:   simple_ptr<T>& operator=(const T& data);
   58: 
   59:   // copy constructor implements counted referencing - no copy is made
   60:   simple_ptr(const simple_ptr<T>& r);
   61:   // assignment of smart pointers implement counted referencing - no copy is made
   62:   simple_ptr<T>& operator=(const simple_ptr<T>&);
   63: 
   64:   // create a pointer containing a dynamically created object
   65:   // Note: the object must be allocated *by the user* with new
   66:   // constructor form - must be called in the form simple_ptr<type> x(new type(args))
   67:   explicit simple_ptr(T* data);
   68:   // assignment form
   69:   simple_ptr<T>& operator= (T* data);
   70: 
   71:   // destructor decrements the reference count and delete only when the last reference is destroyed
   72:   ~simple_ptr(void);
   73: 
   74:   //////////////////////////////////////////////////////////////////////////////
   75:   // logical tests to see if there is anything contained in the pointer since it can be null
   76: 
   77:   // there are two forms:explicit and implicit
   78:   // implicit: if(!r) or if(r)
   79:   // explicit: if(r.null()) or if(r.present())
   80:   operator bool(void) const;
   81:   bool operator!(void) const;
   82:   bool present(void) const;
   83:   bool null(void) const;
   84: 
   85:   //////////////////////////////////////////////////////////////////////////////
   86:   // dereference operators and functions
   87: 
   88:   // dereference the smart pointer to get the object - use in the form *p1
   89:   T& operator*(void) throw(null_dereference);
   90:   const T& operator*(void) const throw(null_dereference);
   91: 
   92:   // used as a prefix to a member access to the contained object e.g. p1->print() calls T::print()
   93:   T* operator->(void) throw(null_dereference);
   94:   const T* operator->(void) const throw(null_dereference);
   95: 
   96:   //////////////////////////////////////////////////////////////////////////////
   97:   // explicit function forms of the above assignment and dereference operators
   98: 
   99:   // set the value
  100:   void set_value(const T& data);
  101:   // get the value
  102:   T& value(void) throw(null_dereference);
  103:   const T& value(void) const throw(null_dereference);
  104: 
  105:   // set the pointer
  106:   // deletes the previous pointer and adopts the passed pointer instead
  107:   // Note: the object must be allocated *by the user* with new
  108:   // Warning: it is very easy to break the memory management with this operation
  109:   void set(T* data = 0);
  110:   // get the pointer
  111:   T* pointer(void);
  112:   const T* pointer(void) const;
  113: 
  114:   //////////////////////////////////////////////////////////////////////////////
  115:   // functions to manage counted referencing
  116: 
  117:   // test whether two pointers point to the same object(known as aliasing the object)
  118:   // used in the form if(a.aliases(b))
  119:   bool aliases(const simple_ptr<T>&) const;
  120: 
  121:   // find the number of aliases - used when you need to know whether an object is still referred to from elsewhere (rare!)
  122:   unsigned alias_count(void) const;
  123: 
  124:   // make this pointer unique with respect to any other references to the same object
  125:   // if this pointer is already unique, it does nothing - otherwise it copies the object
  126:   void make_unique(void);
  127: 
  128:   // delete the object and make the pointer null - does not make it unique first, so all other pointers to this will be null too
  129:   void clear(void);
  130: 
  131:   // make the pointer unique and null in one step - does not affect other pointers that were pointing to the same object
  132:   void clear_unique(void);
  133: 
  134:   // make this pointer a unique copy of the parameter
  135:   // useful for expressions like p1.copy(p2) which makes p1 a pointer to a unique copy of the contents of p2
  136:   void copy(const simple_ptr<T>&);
  137:   // alternate form used in assignments: p1 = ps.copy()
  138:   simple_ptr<T> copy(void) const;
  139: 
  140:   // persistence functions
  141:   void dump(dump_context& str) const throw(persistent_dump_failed);
  142:   void restore(restore_context& str) throw(persistent_restore_failed);
  143: 
  144: protected:
  145:   T* m_pointer;
  146:   unsigned* m_count;
  147: };
  148: 
  149: ////////////////////////////////////////////////////////////////////////////////
  150: // comparisons required for using this class in an STL container
  151: // These require == and < operator in the contained type T
  152: // the remaining relational operators are provided by template functions
  153: // a null pointer is less-than a non-null, two nulls are equal
  154: // these funcions are defined as non-members so that you only need provide
  155: // the underlying T::operator< and == if you are going to use these functions
  156: 
  157: template<typename T>
  158: bool operator==(const simple_ptr<T>&, const simple_ptr<T>&);
  159: 
  160: template<typename T>
  161: bool operator<(const simple_ptr<T>&, const simple_ptr<T>&);
  162: 
  163: ////////////////////////////////////////////////////////////////////////////////
  164: // string/print utilities
  165: 
  166: template<typename T>
  167: std::string simple_ptr_to_string(const simple_ptr<T>& ptr, std::string null_string);
  168: 
  169: template<typename T>
  170: otext& print_simple_ptr(otext& str, const simple_ptr<T>& ptr, std::string null_string);
  171: 
  172: template<typename T>
  173: otext& print_simple_ptr(otext& str, const simple_ptr<T>& ptr, unsigned indent, std::string null_string);
  174: 
  175: ////////////////////////////////////////////////////////////////////////////////
  176: // persistence - call these rather than the methods
  177: // the dump routine dumps simple_ptr-specific information and then calls dump_pointer on the contents
  178: // similarly the restore routine calls restore_pointer
  179: // so therefore the class T should have non-member dump/restore functions
  180: 
  181: template<typename T>
  182: void dump_simple_ptr(dump_context& str, const simple_ptr<T>& data) throw(persistent_dump_failed);
  183: 
  184: template<typename T>
  185: void restore_simple_ptr(restore_context& str, simple_ptr<T>& data) throw(persistent_restore_failed);
  186: 
  187: ////////////////////////////////////////////////////////////////////////////////
  188: ////////////////////////////////////////////////////////////////////////////////
  189: // Cloning simple pointer class for polymorphic class hierarchies
  190: // The contained class T should implement the clonable interface defined in clonable.hpp
  191: ////////////////////////////////////////////////////////////////////////////////
  192: ////////////////////////////////////////////////////////////////////////////////
  193: 
  194: template<typename T>
  195: class simple_ptr_clone
  196: {
  197: public:
  198:   //////////////////////////////////////////////////////////////////////////////
  199:   // member type definitions
  200: 
  201:   typedef T value_type;
  202:   typedef T& reference;
  203:   typedef const T& const_reference;
  204: 
  205:   //////////////////////////////////////////////////////////////////////////////
  206:   // constructors, assignments and destructors
  207: 
  208:   // create a null pointer
  209:   simple_ptr_clone(void);
  210: 
  211:   // create a pointer containing a *copy* of the object
  212:   // this copy is taken because the pointer class maintains a dynamically allocated object 
  213:   // and the T& may not be (usually is not) dynamically allocated
  214:   // constructor form
  215:   simple_ptr_clone(const T& data);
  216:   // assignment form for an already-constructed smart-pointer
  217:   simple_ptr_clone<T>& operator=(const T& data);
  218: 
  219:   // copy constructor implements counted referencing - no copy is made
  220:   simple_ptr_clone(const simple_ptr_clone<T>& r);
  221:   // assignment of smart pointers implement counted referencing - no copy is made
  222:   simple_ptr_clone<T>& operator=(const simple_ptr_clone<T>&);
  223: 
  224:   // create a pointer containing a dynamically created object
  225:   // Note: the object must be allocated *by the user* with new
  226:   // constructor form - must be called in the form simple_ptr_clone<type> x(new type(args))
  227:   explicit simple_ptr_clone(T* data);
  228:   // assignment form
  229:   simple_ptr_clone<T>& operator= (T* data);
  230: 
  231:   // destructor decrements the reference count and delete only when the last reference is destroyed
  232:   ~simple_ptr_clone(void);
  233: 
  234:   //////////////////////////////////////////////////////////////////////////////
  235:   // logical tests to see if there is anything contained in the pointer since it can be null
  236: 
  237:   // there are two forms:explicit and implicit
  238:   // implicit: if(!r) or if(r)
  239:   // explicit: if(r.null()) or if(r.present())
  240:   operator bool(void) const;
  241:   bool operator!(void) const;
  242:   bool present(void) const;
  243:   bool null(void) const;
  244: 
  245:   //////////////////////////////////////////////////////////////////////////////
  246:   // dereference operators and functions
  247: 
  248:   // dereference the smart pointer to get the object - use in the form *p1
  249:   T& operator*(void) throw(null_dereference);
  250:   const T& operator*(void) const throw(null_dereference);
  251: 
  252:   // used as a prefix to a member access to the contained object e.g. p1->print() calls T::print()
  253:   T* operator->(void) throw(null_dereference);
  254:   const T* operator->(void) const throw(null_dereference);
  255: 
  256:   //////////////////////////////////////////////////////////////////////////////
  257:   // explicit function forms of the above assignment and dereference operators
  258: 
  259:   // set the value
  260:   void set_value(const T& data);
  261:   // get the value
  262:   T& value(void) throw(null_dereference);
  263:   const T& value(void) const throw(null_dereference);
  264: 
  265:   // set the pointer
  266:   // deletes the previous pointer and adopts the passed pointer instead
  267:   // Note: the object must be allocated *by the user* with new
  268:   // Warning: it is very easy to break the memory management with this operation
  269:   void set(T* data = 0);
  270:   // get the pointer
  271:   T* pointer(void);
  272:   const T* pointer(void) const;
  273: 
  274:   //////////////////////////////////////////////////////////////////////////////
  275:   // functions to manage counted referencing
  276: 
  277:   // test whether two pointers point to the same object(known as aliasing the object)
  278:   // used in the form if(a.aliases(b))
  279:   bool aliases(const simple_ptr_clone<T>&) const;
  280: 
  281:   // find the number of aliases - used when you need to know whether an object is still referred to from elsewhere (rare!)
  282:   unsigned alias_count(void) const;
  283: 
  284:   // make this pointer unique with respect to any other references to the same object
  285:   // if this pointer is already unique, it does nothing - otherwise it copies the object
  286:   void make_unique(void);
  287: 
  288:   // delete the object and make the pointer null - does not make it unique first, so all other pointers to this will be null too
  289:   void clear(void);
  290: 
  291:   // make the pointer unique and null in one step - does not affect other pointers that were pointing to the same object
  292:   void clear_unique(void);
  293: 
  294:   // make this pointer a unique copy of the parameter
  295:   // useful for expressions like p1.copy(p2) which makes p1 a pointer to a unique copy of the contents of p2
  296:   void copy(const simple_ptr_clone<T>&);
  297:   // alternate form used in assignments: p1 = ps.copy()
  298:   simple_ptr_clone<T> copy(void) const;
  299: 
  300:   // persistence functions
  301:   void dump(dump_context& str) const throw(persistent_dump_failed);
  302:   void restore(restore_context& str) throw(persistent_restore_failed);
  303: 
  304: protected:
  305:   T* m_pointer;
  306:   unsigned* m_count;
  307: };
  308: 
  309: ////////////////////////////////////////////////////////////////////////////////
  310: // comparisons required for using this class in an STL container
  311: // These require == and < operator in the contained type T
  312: // the remaining relational operators are provided by template functions
  313: // a null pointer is less-than a non-null, two nulls are equal
  314: // these funcions are defined as non-members so that you only need provide
  315: // the underlying T::operator< and == if you are going to use these functions
  316: 
  317: template<typename T>
  318: bool operator==(const simple_ptr_clone<T>&, const simple_ptr_clone<T>&);
  319: 
  320: template<typename T>
  321: bool operator<(const simple_ptr_clone<T>&, const simple_ptr_clone<T>&);
  322: 
  323: ////////////////////////////////////////////////////////////////////////////////
  324: // string/print utilities
  325: 
  326: template<typename T>
  327: std::string simple_ptr_clone_to_string(const simple_ptr_clone<T>& ptr, std::string null_string);
  328: 
  329: template<typename T>
  330: otext& print_simple_ptr_clone(otext& str, const simple_ptr_clone<T>& ptr, std::string null_string);
  331: 
  332: template<typename T>
  333: otext& print_simple_ptr_clone(otext& str, const simple_ptr_clone<T>& ptr, unsigned indent, std::string null_string);
  334: 
  335: ////////////////////////////////////////////////////////////////////////////////
  336: // persistence - call these rather than the methods
  337: // the dump routine dumps simple_ptr_clone-specific information and then calls dump_interface
  338: // similarly the restore routine calls restore_interface
  339: // so therefore the class T should implement the persistent interface defined by the class persistent in persistent.hpp
  340: 
  341: template<typename T>
  342: void dump_simple_ptr_clone(dump_context& str, const simple_ptr_clone<T>& data) throw(persistent_dump_failed);
  343: 
  344: template<typename T>
  345: void restore_simple_ptr_clone(restore_context& str, simple_ptr_clone<T>& data) throw(persistent_restore_failed);
  346: 
  347: ////////////////////////////////////////////////////////////////////////////////
  348: ////////////////////////////////////////////////////////////////////////////////
  349: // No-copy simple pointer class for managing objects that cannot be copied
  350: ////////////////////////////////////////////////////////////////////////////////
  351: ////////////////////////////////////////////////////////////////////////////////
  352: 
  353: template<typename T>
  354: class simple_ptr_nocopy
  355: {
  356: public:
  357:   //////////////////////////////////////////////////////////////////////////////
  358:   // member type definitions
  359: 
  360:   typedef T value_type;
  361:   typedef T& reference;
  362:   typedef const T& const_reference;
  363: 
  364:   //////////////////////////////////////////////////////////////////////////////
  365:   // constructors, assignments and destructors
  366: 
  367:   // create a null pointer
  368:   simple_ptr_nocopy(void);
  369: 
  370:   // copy constructor implements counted referencing - no copy is made
  371:   simple_ptr_nocopy(const simple_ptr_nocopy<T>& r);
  372:   // assignment of smart pointers implement counted referencing - no copy is made
  373:   simple_ptr_nocopy<T>& operator=(const simple_ptr_nocopy<T>&);
  374: 
  375:   // create a pointer containing a dynamically created object
  376:   // Note: the object must be allocated *by the user* with new
  377:   // constructor form - must be called in the form simple_ptr_nocopy<type> x(new type(args))
  378:   explicit simple_ptr_nocopy(T* data);
  379:   // assignment form
  380:   simple_ptr_nocopy<T>& operator= (T* data);
  381: 
  382:   // destructor decrements the reference count and delete only when the last reference is destroyed
  383:   ~simple_ptr_nocopy(void);
  384: 
  385:   //////////////////////////////////////////////////////////////////////////////
  386:   // logical tests to see if there is anything contained in the pointer since it can be null
  387: 
  388:   // there are two forms:explicit and implicit
  389:   // implicit: if(!r) or if(r)
  390:   // explicit: if(r.null()) or if(r.present())
  391:   operator bool(void) const;
  392:   bool operator!(void) const;
  393:   bool present(void) const;
  394:   bool null(void) const;
  395: 
  396:   //////////////////////////////////////////////////////////////////////////////
  397:   // dereference operators and functions
  398: 
  399:   // dereference the smart pointer to get the object - use in the form *p1
  400:   T& operator*(void) throw(null_dereference);
  401:   const T& operator*(void) const throw(null_dereference);
  402: 
  403:   // used as a prefix to a member access to the contained object e.g. p1->print() calls T::print()
  404:   T* operator->(void) throw(null_dereference);
  405:   const T* operator->(void) const throw(null_dereference);
  406: 
  407:   //////////////////////////////////////////////////////////////////////////////
  408:   // explicit function forms of the above assignment and dereference operators
  409: 
  410:   // get the value
  411:   T& value(void) throw(null_dereference);
  412:   const T& value(void) const throw(null_dereference);
  413: 
  414:   // set the pointer
  415:   // deletes the previous pointer and adopts the passed pointer instead
  416:   // Note: the object must be allocated *by the user* with new
  417:   // Warning: it is very easy to break the memory management with this operation
  418:   void set(T* data = 0);
  419:   // get the pointer
  420:   T* pointer(void);
  421:   const T* pointer(void) const;
  422: 
  423:   //////////////////////////////////////////////////////////////////////////////
  424:   // functions to manage counted referencing
  425: 
  426:   // test whether two pointers point to the same object(known as aliasing the object)
  427:   // used in the form if(a.aliases(b))
  428:   bool aliases(const simple_ptr_nocopy<T>&) const;
  429: 
  430:   // find the number of aliases - used when you need to know whether an object is still referred to from elsewhere (rare!)
  431:   unsigned alias_count(void) const;
  432: 
  433:   // delete the object and make the pointer null - does not make it unique first, so all other pointers to this will be null too
  434:   void clear(void);
  435: 
  436:   // make the pointer unique and null in one step - does not affect other pointers that were pointing to the same object
  437:   void clear_unique(void);
  438: 
  439: protected:
  440:   T* m_pointer;
  441:   unsigned* m_count;
  442: };
  443: 
  444: ////////////////////////////////////////////////////////////////////////////////
  445: // comparisons required for using this class in an STL container
  446: // These require == and < operator in the contained type T
  447: // the remaining relational operators are provided by template functions
  448: // a null pointer is less-than a non-null, two nulls are equal
  449: // these funcions are defined as non-members so that you only need provide
  450: // the underlying T::operator< and == if you are going to use these functions
  451: 
  452: template<typename T>
  453: bool operator==(const simple_ptr_nocopy<T>&, const simple_ptr_nocopy<T>&);
  454: 
  455: template<typename T>
  456: bool operator<(const simple_ptr_nocopy<T>&, const simple_ptr_nocopy<T>&);
  457: 
  458: ////////////////////////////////////////////////////////////////////////////////
  459: // string/print utilities
  460: 
  461: template<typename T>
  462: std::string simple_ptr_nocopy_to_string(const simple_ptr_nocopy<T>& ptr, std::string null_string);
  463: 
  464: template<typename T>
  465: otext& print_simple_ptr_nocopy(otext& str, const simple_ptr_nocopy<T>& ptr, std::string null_string);
  466: 
  467: template<typename T>
  468: otext& print_simple_ptr_nocopy(otext& str, const simple_ptr_nocopy<T>& ptr, unsigned indent, std::string null_string);
  469: 
  470: ////////////////////////////////////////////////////////////////////////////////
  471: // there's no persistence on simple_ptr_nocopy because the whole point is that
  472: // it stores an uncopyable object and persistence is a form of copying
  473: 
  474: ////////////////////////////////////////////////////////////////////////////////
  475: ////////////////////////////////////////////////////////////////////////////////
  476: // Simple smart pointer class
  477: ////////////////////////////////////////////////////////////////////////////////
  478: ////////////////////////////////////////////////////////////////////////////////
  479: 
  480: ////////////////////////////////////////////////////////////////////////////////
  481: // internals
  482: 
  483: template<typename T> class smart_ptr_holder;
  484: 
  485: ////////////////////////////////////////////////////////////////////////////////
  486: 
  487: template<typename T>
  488: class smart_ptr
  489: {
  490: public:
  491:   //////////////////////////////////////////////////////////////////////////////
  492:   // member type definitions
  493: 
  494:   typedef T value_type;
  495:   typedef T& reference;
  496:   typedef const T& const_reference;
  497: 
  498:   //////////////////////////////////////////////////////////////////////////////
  499:   // constructors, assignments and destructors
  500: 
  501:   // create a null pointer
  502:   smart_ptr(void);
  503: 
  504:   // create a pointer containing a *copy* of the object
  505:   // this copy is taken because the pointer class maintains a dynamically allocated object 
  506:   // and the T& may not be (usually is not) dynamically allocated
  507:   // constructor form
  508:   smart_ptr(const T& data);
  509:   // assignment form for an already-constructed smart-pointer
  510:   smart_ptr<T>& operator=(const T& data);
  511: 
  512:   // copy constructor implements counted referencing - no copy is made
  513:   smart_ptr(const smart_ptr<T>& r);
  514:   // assignment of smart pointers implement counted referencing - no copy is made
  515:   smart_ptr<T>& operator=(const smart_ptr<T>&);
  516: 
  517:   // create a pointer containing a dynamically created object
  518:   // Note: the object must be allocated *by the user* with new
  519:   // constructor form - must be called in the form smart_ptr<type> x(new type(args))
  520:   explicit smart_ptr(T* data);
  521:   // assignment form
  522:   smart_ptr<T>& operator= (T* data);
  523: 
  524:   // destructor decrements the reference count and delete only when the last reference is destroyed
  525:   ~smart_ptr(void);
  526: 
  527:   //////////////////////////////////////////////////////////////////////////////
  528:   // logical tests to see if there is anything contained in the pointer since it can be null
  529: 
  530:   // there are two forms:explicit and implicit
  531:   // implicit: if(!r) or if(r)
  532:   // explicit: if(r.null()) or if(r.present())
  533:   operator bool(void) const;
  534:   bool operator!(void) const;
  535:   bool present(void) const;
  536:   bool null(void) const;
  537: 
  538:   //////////////////////////////////////////////////////////////////////////////
  539:   // dereference operators and functions
  540: 
  541:   // dereference the smart pointer to get the object - use in the form *p1
  542:   T& operator*(void) throw(null_dereference);
  543:   const T& operator*(void) const throw(null_dereference);
  544: 
  545:   // used as a prefix to a member access to the contained object e.g. p1->print() calls T::print()
  546:   T* operator->(void) throw(null_dereference);
  547:   const T* operator->(void) const throw(null_dereference);
  548: 
  549:   //////////////////////////////////////////////////////////////////////////////
  550:   // explicit function forms of the above assignment and dereference operators
  551: 
  552:   // set the value
  553:   void set_value(const T& data);
  554:   // get the value
  555:   T& value(void) throw(null_dereference);
  556:   const T& value(void) const throw(null_dereference);
  557: 
  558:   // set the pointer
  559:   // deletes the previous pointer and adopts the passed pointer instead
  560:   // Note: the object must be allocated *by the user* with new
  561:   // Warning: it is very easy to break the memory management with this operation
  562:   void set(T* data = 0);
  563:   // get the pointer
  564:   T* pointer(void);
  565:   const T* pointer(void) const;
  566: 
  567:   //////////////////////////////////////////////////////////////////////////////
  568:   // functions to manage counted referencing
  569: 
  570:   // test whether two pointers point to the same object(known as aliasing the object)
  571:   // used in the form if(a.aliases(b))
  572:   bool aliases(const smart_ptr<T>&) const;
  573: 
  574:   // find the number of aliases - used when you need to know whether an object is still referred to from elsewhere (rare!)
  575:   unsigned alias_count(void) const;
  576: 
  577:   // make this pointer unique with respect to any other references to the same object
  578:   // if this pointer is already unique, it does nothing - otherwise it copies the object
  579:   void make_unique(void);
  580: 
  581:   // delete the object and make the pointer null - does not make it unique first, so all other pointers to this will be null too
  582:   void clear(void);
  583: 
  584:   // make the pointer unique and null in one step - does not affect other pointers that were pointing to the same object
  585:   void clear_unique(void);
  586: 
  587:   // make this pointer a unique copy of the parameter
  588:   // useful for expressions like p1.copy(p2) which makes p1 a pointer to a unique copy of the contents of p2
  589:   void copy(const smart_ptr<T>&);
  590:   // alternate form used in assignments: p1 = ps.copy()
  591:   smart_ptr<T> copy(void) const;
  592: 
  593:   // persistence functions
  594:   void dump(dump_context& str) const throw(persistent_dump_failed);
  595:   void restore(restore_context& str) throw(persistent_restore_failed);
  596: 
  597: protected:
  598:   smart_ptr_holder<T>* m_holder;
  599: };
  600: 
  601: ////////////////////////////////////////////////////////////////////////////////
  602: // comparisons required for using this class in an STL container
  603: // These require == and < operator in the contained type T
  604: // the remaining relational operators are provided by template functions
  605: // a null pointer is less-than a non-null, two nulls are equal
  606: // these funcions are defined as non-members so that you only need provide
  607: // the underlying T::operator< and == if you are going to use these functions
  608: 
  609: template<typename T>
  610: bool operator==(const smart_ptr<T>&, const smart_ptr<T>&);
  611: 
  612: template<typename T>
  613: bool operator<(const smart_ptr<T>&, const smart_ptr<T>&);
  614: 
  615: ////////////////////////////////////////////////////////////////////////////////
  616: // string/print utilities
  617: 
  618: template<typename T>
  619: std::string smart_ptr_to_string(const smart_ptr<T>& ptr, std::string null_string);
  620: 
  621: template<typename T>
  622: otext& print_smart_ptr(otext& str, const smart_ptr<T>& ptr, std::string null_string);
  623: 
  624: template<typename T>
  625: otext& print_smart_ptr(otext& str, const smart_ptr<T>& ptr, unsigned indent, std::string null_string);
  626: 
  627: ////////////////////////////////////////////////////////////////////////////////
  628: // persistence - call these rather than the methods
  629: // the dump routine dumps smart_ptr-specific information and then calls dump_pointer on the contents
  630: // similarly the restore routine calls restore_pointer
  631: // so therefore the class T should have non-member dump/restore functions
  632: 
  633: template<typename T>
  634: void dump_smart_ptr(dump_context& str, const smart_ptr<T>& data) throw(persistent_dump_failed);
  635: 
  636: template<typename T>
  637: void restore_smart_ptr(restore_context& str, smart_ptr<T>& data) throw(persistent_restore_failed);
  638: 
  639: ////////////////////////////////////////////////////////////////////////////////
  640: ////////////////////////////////////////////////////////////////////////////////
  641: // Cloning smart pointer class for polymorphic class hierarchies
  642: // The contained class T should implement the clonable interface defined in clonable.hpp
  643: ////////////////////////////////////////////////////////////////////////////////
  644: ////////////////////////////////////////////////////////////////////////////////
  645: 
  646: template<typename T>
  647: class smart_ptr_clone
  648: {
  649: public:
  650:   //////////////////////////////////////////////////////////////////////////////
  651:   // member type definitions
  652: 
  653:   typedef T value_type;
  654:   typedef T& reference;
  655:   typedef const T& const_reference;
  656: 
  657:   //////////////////////////////////////////////////////////////////////////////
  658:   // constructors, assignments and destructors
  659: 
  660:   // create a null pointer
  661:   smart_ptr_clone(void);
  662: 
  663:   // create a pointer containing a *copy* of the object
  664:   // this copy is taken because the pointer class maintains a dynamically allocated object 
  665:   // and the T& may not be (usually is not) dynamically allocated
  666:   // constructor form
  667:   smart_ptr_clone(const T& data);
  668:   // assignment form for an already-constructed smart-pointer
  669:   smart_ptr_clone<T>& operator=(const T& data);
  670: 
  671:   // copy constructor implements counted referencing - no copy is made
  672:   smart_ptr_clone(const smart_ptr_clone<T>& r);
  673:   // assignment of smart pointers implement counted referencing - no copy is made
  674:   smart_ptr_clone<T>& operator=(const smart_ptr_clone<T>&);
  675: 
  676:   // create a pointer containing a dynamically created object
  677:   // Note: the object must be allocated *by the user* with new
  678:   // constructor form - must be called in the form smart_ptr_clone<type> x(new type(args))
  679:   explicit smart_ptr_clone(T* data);
  680:   // assignment form
  681:   smart_ptr_clone<T>& operator= (T* data);
  682: 
  683:   // destructor decrements the reference count and delete only when the last reference is destroyed
  684:   ~smart_ptr_clone(void);
  685: 
  686:   //////////////////////////////////////////////////////////////////////////////
  687:   // logical tests to see if there is anything contained in the pointer since it can be null
  688: 
  689:   // there are two forms:explicit and implicit
  690:   // implicit: if(!r) or if(r)
  691:   // explicit: if(r.null()) or if(r.present())
  692:   operator bool(void) const;
  693:   bool operator!(void) const;
  694:   bool present(void) const;
  695:   bool null(void) const;
  696: 
  697:   //////////////////////////////////////////////////////////////////////////////
  698:   // dereference operators and functions
  699: 
  700:   // dereference the smart pointer to get the object - use in the form *p1
  701:   T& operator*(void) throw(null_dereference);
  702:   const T& operator*(void) const throw(null_dereference);
  703: 
  704:   // used as a prefix to a member access to the contained object e.g. p1->print() calls T::print()
  705:   T* operator->(void) throw(null_dereference);
  706:   const T* operator->(void) const throw(null_dereference);
  707: 
  708:   //////////////////////////////////////////////////////////////////////////////
  709:   // explicit function forms of the above assignment and dereference operators
  710: 
  711:   // set the value
  712:   void set_value(const T& data);
  713:   // get the value
  714:   T& value(void) throw(null_dereference);
  715:   const T& value(void) const throw(null_dereference);
  716: 
  717:   // set the pointer
  718:   // deletes the previous pointer and adopts the passed pointer instead
  719:   // Note: the object must be allocated *by the user* with new
  720:   // Warning: it is very easy to break the memory management with this operation
  721:   void set(T* data = 0);
  722:   // get the pointer
  723:   T* pointer(void);
  724:   const T* pointer(void) const;
  725: 
  726:   //////////////////////////////////////////////////////////////////////////////
  727:   // functions to manage counted referencing
  728: 
  729:   // test whether two pointers point to the same object(known as aliasing the object)
  730:   // used in the form if(a.aliases(b))
  731:   bool aliases(const smart_ptr_clone<T>&) const;
  732: 
  733:   // find the number of aliases - used when you need to know whether an object is still referred to from elsewhere (rare!)
  734:   unsigned alias_count(void) const;
  735: 
  736:   // make this pointer unique with respect to any other references to the same object
  737:   // if this pointer is already unique, it does nothing - otherwise it copies the object
  738:   void make_unique(void);
  739: 
  740:   // delete the object and make the pointer null - does not make it unique first, so all other pointers to this will be null too
  741:   void clear(void);
  742: 
  743:   // make the pointer unique and null in one step - does not affect other pointers that were pointing to the same object
  744:   void clear_unique(void);
  745: 
  746:   // make this pointer a unique copy of the parameter
  747:   // useful for expressions like p1.copy(p2) which makes p1 a pointer to a unique copy of the contents of p2
  748:   void copy(const smart_ptr_clone<T>&);
  749:   // alternate form used in assignments: p1 = ps.copy()
  750:   smart_ptr_clone<T> copy(void) const;
  751: 
  752:   // persistence functions
  753:   void dump(dump_context& str) const throw(persistent_dump_failed);
  754:   void restore(restore_context& str) throw(persistent_restore_failed);
  755: 
  756: protected:
  757:   smart_ptr_holder<T>* m_holder;
  758: };
  759: 
  760: ////////////////////////////////////////////////////////////////////////////////
  761: // comparisons required for using this class in an STL container
  762: // These require == and < operator in the contained type T
  763: // the remaining relational operators are provided by template functions
  764: // a null pointer is less-than a non-null, two nulls are equal
  765: // these funcions are defined as non-members so that you only need provide
  766: // the underlying T::operator< and == if you are going to use these functions
  767: 
  768: template<typename T>
  769: bool operator==(const smart_ptr_clone<T>&, const smart_ptr_clone<T>&);
  770: 
  771: template<typename T>
  772: bool operator<(const smart_ptr_clone<T>&, const smart_ptr_clone<T>&);
  773: 
  774: ////////////////////////////////////////////////////////////////////////////////
  775: // string/print utilities
  776: 
  777: template<typename T>
  778: std::string smart_ptr_clone_to_string(const smart_ptr_clone<T>& ptr, std::string null_string);
  779: 
  780: template<typename T>
  781: otext& print_smart_ptr_clone(otext& str, const smart_ptr_clone<T>& ptr, std::string null_string);
  782: 
  783: template<typename T>
  784: otext& print_smart_ptr_clone(otext& str, const smart_ptr_clone<T>& ptr, unsigned indent, std::string null_string);
  785: 
  786: ////////////////////////////////////////////////////////////////////////////////
  787: // persistence - call these rather than the methods
  788: // the dump routine dumps smart_ptr_clone-specific information and then calls dump_interface
  789: // similarly the restore routine calls restore_interface
  790: // so therefore the class T should implement the persistent interface defined by the class persistent in persistent.hpp
  791: 
  792: template<typename T>
  793: void dump_smart_ptr_clone(dump_context& str, const smart_ptr_clone<T>& data) throw(persistent_dump_failed);
  794: 
  795: template<typename T>
  796: void restore_smart_ptr_clone(restore_context& str, smart_ptr_clone<T>& data) throw(persistent_restore_failed);
  797: 
  798: ////////////////////////////////////////////////////////////////////////////////
  799: ////////////////////////////////////////////////////////////////////////////////
  800: // No-copy smart pointer class for managing objects that cannot be copied
  801: ////////////////////////////////////////////////////////////////////////////////
  802: ////////////////////////////////////////////////////////////////////////////////
  803: 
  804: template<typename T>
  805: class smart_ptr_nocopy
  806: {
  807: public:
  808:   //////////////////////////////////////////////////////////////////////////////
  809:   // member type definitions
  810: 
  811:   typedef T value_type;
  812:   typedef T& reference;
  813:   typedef const T& const_reference;
  814: 
  815:   //////////////////////////////////////////////////////////////////////////////
  816:   // constructors, assignments and destructors
  817: 
  818:   // create a null pointer
  819:   smart_ptr_nocopy(void);
  820: 
  821:   // copy constructor implements counted referencing - no copy is made
  822:   smart_ptr_nocopy(const smart_ptr_nocopy<T>& r);
  823:   // assignment of smart pointers implement counted referencing - no copy is made
  824:   smart_ptr_nocopy<T>& operator=(const smart_ptr_nocopy<T>&);
  825: 
  826:   // create a pointer containing a dynamically created object
  827:   // Note: the object must be allocated *by the user* with new
  828:   // constructor form - must be called in the form smart_ptr_nocopy<type> x(new type(args))
  829:   explicit smart_ptr_nocopy(T* data);
  830:   // assignment form
  831:   smart_ptr_nocopy<T>& operator= (T* data);
  832: 
  833:   // destructor decrements the reference count and delete only when the last reference is destroyed
  834:   ~smart_ptr_nocopy(void);
  835: 
  836:   //////////////////////////////////////////////////////////////////////////////
  837:   // logical tests to see if there is anything contained in the pointer since it can be null
  838: 
  839:   // there are two forms:explicit and implicit
  840:   // implicit: if(!r) or if(r)
  841:   // explicit: if(r.null()) or if(r.present())
  842:   operator bool(void) const;
  843:   bool operator!(void) const;
  844:   bool present(void) const;
  845:   bool null(void) const;
  846: 
  847:   //////////////////////////////////////////////////////////////////////////////
  848:   // dereference operators and functions
  849: 
  850:   // dereference the smart pointer to get the object - use in the form *p1
  851:   T& operator*(void) throw(null_dereference);
  852:   const T& operator*(void) const throw(null_dereference);
  853: 
  854:   // used as a prefix to a member access to the contained object e.g. p1->print() calls T::print()
  855:   T* operator->(void) throw(null_dereference);
  856:   const T* operator->(void) const throw(null_dereference);
  857: 
  858:   //////////////////////////////////////////////////////////////////////////////
  859:   // explicit function forms of the above assignment and dereference operators
  860: 
  861:   // get the value
  862:   T& value(void) throw(null_dereference);
  863:   const T& value(void) const throw(null_dereference);
  864: 
  865:   // set the pointer
  866:   // deletes the previous pointer and adopts the passed pointer instead
  867:   // Note: the object must be allocated *by the user* with new
  868:   // Warning: it is very easy to break the memory management with this operation
  869:   void set(T* data = 0);
  870:   // get the pointer
  871:   T* pointer(void);
  872:   const T* pointer(void) const;
  873: 
  874:   //////////////////////////////////////////////////////////////////////////////
  875:   // functions to manage counted referencing
  876: 
  877:   // test whether two pointers point to the same object(known as aliasing the object)
  878:   // used in the form if(a.aliases(b))
  879:   bool aliases(const smart_ptr_nocopy<T>&) const;
  880: 
  881:   // find the number of aliases - used when you need to know whether an object is still referred to from elsewhere (rare!)
  882:   unsigned alias_count(void) const;
  883: 
  884:   // delete the object and make the pointer null - does not make it unique first, so all other pointers to this will be null too
  885:   void clear(void);
  886: 
  887:   // make the pointer unique and null in one step - does not affect other pointers that were pointing to the same object
  888:   void clear_unique(void);
  889: 
  890: protected:
  891:   smart_ptr_holder<T>* m_holder;
  892: };
  893: 
  894: ////////////////////////////////////////////////////////////////////////////////
  895: // comparisons required for using this class in an STL container
  896: // These require == and < operator in the contained type T
  897: // the remaining relational operators are provided by template functions
  898: // a null pointer is less-than a non-null, two nulls are equal
  899: // these funcions are defined as non-members so that you only need provide
  900: // the underlying T::operator< and == if you are going to use these functions
  901: 
  902: template<typename T>
  903: bool operator==(const smart_ptr_nocopy<T>&, const smart_ptr_nocopy<T>&);
  904: 
  905: template<typename T>
  906: bool operator<(const smart_ptr_nocopy<T>&, const smart_ptr_nocopy<T>&);
  907: 
  908: ////////////////////////////////////////////////////////////////////////////////
  909: // string/print utilities
  910: 
  911: template<typename T>
  912: std::string smart_ptr_nocopy_to_string(const smart_ptr_nocopy<T>& ptr, std::string null_string);
  913: 
  914: template<typename T>
  915: otext& print_smart_ptr_nocopy(otext& str, const smart_ptr_nocopy<T>& ptr, std::string null_string);
  916: 
  917: template<typename T>
  918: otext& print_smart_ptr_nocopy(otext& str, const smart_ptr_nocopy<T>& ptr, unsigned indent, std::string null_string);
  919: 
  920: ////////////////////////////////////////////////////////////////////////////////
  921: // there's no persistence on smart_ptr_nocopy because the whole point is that
  922: // it stores an uncopyable object and persistence is a form of copying
  923: 
  924: ////////////////////////////////////////////////////////////////////////////////
  925: #include "smart_ptr.tpp"
  926: #endif