#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