# containers/safe_iterator.hpp

    #ifndef STLPLUS_SAFE_ITERATOR
    #define STLPLUS_SAFE_ITERATOR
    ////////////////////////////////////////////////////////////////////////////////

    //   Author:    Andy Rushton
    //   Copyright: (c) Southampton University 1999-2004
    //              (c) Andy Rushton           2004 onwards
    //   License:   BSD License, see ../docs/license.html

    //   The STLplus safe_iterator superclasses. This implements the STLplus safe
    //   iterator principles. Data structures can then be built using subclasses
    //   of safe_iterator for their iterator objects and they will inherit the
    //   safe iterator behaviour.

    //   The data structure must contain a master iterator for each node in the
    //   structure. When an iterator is returned to the user, it must be created
    //   by the master iterator. When a node is removed from the data structure,
    //   its master iterator is destroyed. This sets all iterators pointing to the
    //   master iterator to end iterators.

    ////////////////////////////////////////////////////////////////////////////////
    #include "containers_fixes.hpp"
    #include "exceptions.hpp"

    namespace stlplus
    {

      ////////////////////////////////////////////////////////////////////////////////
      // internals

      template<typename O, typename N>
      class safe_iterator_body;

      template<typename O, typename N>
      class safe_iterator;

      ////////////////////////////////////////////////////////////////////////////////
      // Master Iterator
      // Create one of these in each node in the data structure
      // Generate iterators by obtaining a safe-iterator object from the master iterator
      ////////////////////////////////////////////////////////////////////////////////

      template<typename O, typename N>
      class master_iterator
      {
      public:

        // construct a valid master iterator connected to the node
        master_iterator(const O* owner, N* node) ;

        // destructor - disconnects all iterators from the node
        ~master_iterator(void) ;

        // dereference
        N* node(void) const ;
        const O* owner(void) const ;

        // when you move a node from one owner to another, call this on the node's master iterator
        // this effectively moves all other iterators to the node so that they are owned by the new owner too
        void change_owner(const O* owner) ;

        friend class safe_iterator<O,N>;
      private:
        master_iterator(const master_iterator&) ;
        master_iterator& operator=(const master_iterator&) ;
        safe_iterator_body<O,N>* m_body;
      };

      ////////////////////////////////////////////////////////////////////////////////
      // Safe Iterator
      ////////////////////////////////////////////////////////////////////////////////

      template<typename O, typename N>
      class safe_iterator
      {
      public:
        // constructors
        // an iterator has three possible states: null, valid or end
        // null iterators are not owned, valid and end iterators are owned and can only be used on the owner data structure
        // constructors for each of theses states

        // construct a null iterator
        safe_iterator(void) ;

        // construct a valid iterator from the owner node's master iterator
        safe_iterator(const master_iterator<O,N>&) ;

        // construct an end iterator
        safe_iterator(const O* owner) ;

        // copy operators

        // copy constructor creates a safe iterator with the same properties as the source
        safe_iterator(const safe_iterator<O,N>&) ;

        // copy an iterator by assignment
        safe_iterator<O,N>& operator=(const safe_iterator<O,N>&) ;

        // destructor
        ~safe_iterator(void) ;

        // changing the state of an iterator, e.g. during traversal

        // reassignment to another node - used in increment/decrement operation
        void set(const master_iterator<O,N>&) ;

        // change to an end iterator - e.g. as a result of incrementing off the end
        void set_end(void) ;

        // change to a null iterator - i.e. one that does not belong to any object
        void set_null(void) ;

        // dereference operators to access the internal state

        // get the node that this iterator points to
        N* node(void) const ;
        // get the owner data structure
        const O* owner(void) const ;

        ////////////////////////////////////////////////////////////////////////////////
        // status tests

        // comparison
        bool equal(const safe_iterator<O,N>& right) const ;
        int compare(const safe_iterator<O,N>& right) const ;

        // a null iterator is one that has not been initialised with a value yet
        // i.e. you just declared it but didn't assign to it
        bool null(void) const ;

        // an end iterator is one that points to the end element of the list of nodes
        // in STL conventions this is one past the last valid element and must not be dereferenced
        bool end(void) const ;

        // a valid iterator is one that can be dereferenced
        // i.e. non-null and non-end
        bool valid(void) const ;

        // check ownership of an iterator
        bool owned_by(const O* owner) const;

        // check the rules for an iterator

        // assert the rules for a valid iterator
        // optionally also check that the iterator is owned by the owner
        // exceptions: wrong_object,null_dereference,end_dereference
        void assert_valid(const O* owner = 0) const ;
        // assert the rules for a non-null iterator - i.e. valid or end, values that occur in increment operations
        // optionally also check that the iterator is owned by the owner
        // exceptions: wrong_object,null_dereference
        void assert_non_null(const O* owner = 0) const ;
        // assert that this iterator is owned by this container
        // exceptions: wrong_object
        void assert_owner(const O* owner) const ;

        ////////////////////////////////////////////////////////////////////////////////

        friend class master_iterator<O,N>;
      private:
        safe_iterator_body<O,N>* m_body;
      };

      ////////////////////////////////////////////////////////////////////////////////

    } // end namespace stlplus

    #include "safe_iterator.tpp"
    #endif