#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