#ifndef ARG_AUTO_PTR_H
#define ARG_AUTO_PTR_H
#ifndef ARG_COMPILER_H
#include "arg_compiler.h"
#endif
namespace arg 
{ 
    template <class my_element_type> 
    class auto_ptr 
    { 
        template <class an_element_type> 
        struct auto_ptr_ref 
        { 
            auto_ptr<an_element_type>& ref; 
            auto_ptr_ref(auto_ptr<an_element_type>& rhs) 
            : ref(rhs) 
            { 
            } 
        }; 
        
      public: 
        typedef my_element_type element_type; 
        explicit auto_ptr(my_element_type* ptr = 0) throw() 
        : p(ptr) 
        { 
        } 
        template <class rhs_element_type> 
        auto_ptr(auto_ptr<rhs_element_type>& rhs) throw() 
        : p(rhs.release()) 
        { 
        } 
  
        auto_ptr(auto_ptr& rhs) throw() 
        : p(rhs.release()) 
        { 
        } 
        
        template <class rhs_element_type> 
        auto_ptr& operator=(auto_ptr<rhs_element_type>& rhs) throw() 
        { 
            reset(rhs.release()); 
            return *this; 
        } 
  
        auto_ptr& operator=(auto_ptr& rhs) throw() 
        { 
            reset(rhs.release()); 
            return *this; 
        } 
        
        ~auto_ptr() throw() 
        { 
            delete p; 
        } 
        my_element_type* get() const throw() 
        { 
            return p; 
        } 
        
        my_element_type& operator*() const throw() 
        { 
            return *p; 
        } 
        
        
        my_element_type* operator->() const throw() 
        { 
            return p; 
        } 
        my_element_type* release() throw() 
        { 
            my_element_type* temp = p;
            p = 0; 
            return temp; 
        } 
        void reset(my_element_type* ptr=0) throw() 
        { 
            my_element_type* temp = p;
            p = ptr; 
            delete temp; 
        } 
        auto_ptr(auto_ptr_ref<my_element_type> rhs) throw() // NB rhs passed by _value_
        : p(rhs.ref.release()) 
        { 
        }
        
        template <class an_element_type> 
        operator auto_ptr_ref<an_element_type>() throw() 
        { 
            return auto_ptr_ref<an_element_type>(*this); 
        } 
        
        template <class an_element_type> 
        operator auto_ptr<an_element_type>() throw() 
        { 
            return auto_ptr<an_element_type>(release()); 
        } 
      private: 
      
        my_element_type* p;        // refers to the actual owned object(if any) 
    }; 
} 
#endif