Main Page   Namespace List   Class Hierarchy   Compound List   File List   Header Files   Namespace Members   Compound Members   File Members  

arg_shared.h

This is the verbatim text of the arg_shared.h include file.

#ifndef ARG_SHARED_H
#define ARG_SHARED_H

#ifndef ARG_COMPILER_H
#include "arg_compiler.h"
#endif

namespace arg
{
    class generic_reference
    {
    public:
        typedef void (*delete_ftn)(void* pointee);
        
    protected:
        
        void swap(generic_reference& with) throw();

        generic_reference(void* pointee, delete_ftn do_delete);
        
        generic_reference(const generic_reference& rhs);
        
        virtual ~generic_reference() throw();
        
        generic_reference& operator=(const generic_reference& rhs);
        
        void increment_strong_references() const;

        void decrement_strong_references() const;
        
        bool less(void*) const throw();

        void* get() const;
        
        static void* get(const generic_reference& rhs) { return rhs.get(); }
    
    private:
        class counted_ptr_body;
        counted_ptr_body* body;
    };


    template<typename pointee_type>
    class typed_reference : public generic_reference
    {
    public:

        typed_reference(pointee_type* pointee) 
        : generic_reference(
            pointee, 
            &typed_reference::do_delete)
        { 
        }

// The following constructor and assignment lead to the pointer conversion
// chain "derived" -> "void*" -> "base*" which isn't guaranteed to work.
// (In practice it works in many circumstances.)
//
// Pending inspiration on a safe way to provide this facility together
// with the counted/uncounted support I've disabled them. {arg 20-Oct-99}
#ifdef ARG_UNSAFE_XVERT
        // Templated copy construction - for upcasting/const conversion
        template<typename rhs_pointee_type>
        typed_reference(
            const typed_reference<rhs_pointee_type>& rhs)
        : generic_reference(rhs)
        {
            // compile time type compatability check - does nothing at runtime
            { rhs_pointee_type* pr= 0; pointee_type* pl= 0; pl = pr; }
        }
        
        // Templated assignment - for upcasting/const conversion
        template<typename rhs_pointee_type>
        typed_reference& operator=(
            const typed_reference<rhs_pointee_type>& rhs)
        {
            // compile time type compatability check - does nothing at runtime
            { rhs_pointee_type* pr= 0; pointee_type* pl= 0; pl = pr; }
            generic_reference::operator=(rhs);
            return *this;
        }
#endif      

        void swap(typed_reference& with) throw()
        {
            generic_reference::swap(with);
        }


        template<typename rhs_pointee_type>
        bool operator==(
            const typed_reference<rhs_pointee_type>& rhs) const
        {
            return get() == get(rhs);
        }

        template<typename rhs_pointee_type>
        bool operator!=(
            const typed_reference<rhs_pointee_type>& rhs) const
        {
            return get() != rhs.get();
        }

        template<typename rhs_pointee_type>
        bool operator<(
            const typed_reference<rhs_pointee_type>& rhs) const
        {
            return less(rhs.get());
        }

    protected:

        void increment_strong_references() const
        {
            generic_reference::increment_strong_references();
        }
        
    private:

        // Provide a type-safe deletion function
        static void do_delete(void* pointee) throw()
        {
            delete static_cast<pointee_type*>(pointee);
        }
    };
    

    template<typename pointee_type>
    class counted_ptr : 
        public  typed_reference<pointee_type>
    {
        typedef typed_reference<pointee_type> base_type;
        
    public:
    
    //  Construction

        counted_ptr() 
        : base_type(static_cast<pointee_type*>(0)) 
        {
            increment_strong_references();
        }
        
        explicit counted_ptr(pointee_type* p) 
        : base_type(p) 
        {
            increment_strong_references();
        }
        
        counted_ptr(const counted_ptr& rhs)
        : base_type(rhs)
        {
            increment_strong_references();
        }

#ifdef ARG_UNSAFE_XVERT
        template<typename rhs_pointee_type>
        counted_ptr(
            const typed_reference<rhs_pointee_type>& rhs)
        : base_type(rhs)
        {
            increment_strong_references();
        }
#else
        counted_ptr(const base_type& rhs)
        : base_type(rhs)
        {
            increment_strong_references();
        }
#endif

        ~counted_ptr() throw()
        {
            decrement_strong_references();
        }

    
    //  Accessors

        pointee_type* get() const 
        {
            return static_cast<pointee_type*>(base_type::get());
        }
    
        pointee_type* operator->() const
        {
            return static_cast<pointee_type*>(base_type::get());
        }
    
        pointee_type& operator*() const
        {
            return *static_cast<pointee_type*>(base_type::get());
        }

    
    //  Mutators

#ifdef ARG_UNSAFE_XVERT
        template<typename rhs_pointee_type>
        counted_ptr& operator=(
            const typed_reference<rhs_pointee_type>& rhs)
        {
            rhs.increment_strong_references();
            decrement_strong_references();
            base_type::operator=(rhs);
            return *this;
        }
#endif

        counted_ptr& operator=(const base_type& rhs)
        {
            rhs.increment_strong_references();
            decrement_strong_references();
            base_type::operator=(rhs);
            return *this;
        }

        counted_ptr& operator=(const counted_ptr& rhs)
        {
            rhs.increment_strong_references();
            decrement_strong_references();
            base_type::operator=(rhs);
            return *this;
        }

        void reset(pointee_type* p)
        {
            counted_ptr tmp(p);
            base_type::swap(tmp);
        }
        
        void swap(base_type& with) throw()
        {
            base_type::swap(with);
        }

    };


    template<typename pointee_type>
    class uncounted_ptr : public typed_reference<pointee_type>
    {
        typedef typed_reference<pointee_type> base_type;
        
    public:
    
    //  Construction

        uncounted_ptr() 
        : base_type(static_cast<pointee_type*>(0)) 
        {
        }

        
#ifdef ARG_UNSAFE_XVERT
        template<typename rhs_pointee_type>
        uncounted_ptr(
            const typed_reference<rhs_pointee_type>& rhs)
        : base_type(rhs)
        {
        }
#else
        uncounted_ptr(const base_type& rhs)
        : base_type(rhs)
        {
        }
#endif

        ~uncounted_ptr() throw()
        {
        }

    
    //  Accessors

        pointee_type* get() const 
        {
            return static_cast<pointee_type*>(base_type::get());
        }
    
        pointee_type* operator->() const
        {
            return static_cast<pointee_type*>(base_type::get());
        }
    
        pointee_type& operator*() const
        {
            return static_cast<pointee_type&>(*base_type::get());
        }

    
    //  Mutators

#ifdef ARG_UNSAFE_XVERT
        template<typename rhs_pointee_type>
        uncounted_ptr& operator=(
            const typed_reference<rhs_pointee_type>& rhs)
        {
            base_type::operator=(rhs);
            return *this;
        }
#else
        uncounted_ptr& operator=(const base_type& rhs)
        {
            base_type::operator=(rhs);
            return *this;
        }
#endif

        void reset(pointee_type* p)
        {
            base_type tmp(p);
            base_type::swap(tmp);
        }
        
        void swap(base_type& with) throw()
        {
            base_type::swap(with);
        }

    };
}

namespace std
{
    template<typename pointee_type>
    inline
    void swap(
        ::arg::typed_reference<pointee_type>& lhs, 
        ::arg::typed_reference<pointee_type>& rhs) throw()
    {
        lhs.swap(rhs);
    }

}
#endif

Copyright 1999-2000 Alan Griffiths