$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: David B. Held (dheld_at_[hidden])
Date: 2003-02-06 21:42:01
I need a pointer that can store pointer or an ID. I thought maybe
I could make a policy set for smart_ptr, but that turns out to be
too tricky. I don't think this kind of thing is appropriate for a
smart pointer because of the interface, but I just wanted to get
some opinions on the technique, and see if there are any
improvements to be made.
#include <cstring> // std::memcpy()
#include <new> // placement new
#include <algorithm> // std::swap()
#include <stdexcept> // std::runtime_error
#include <boost/shared_ptr.hpp>
//--------------------------------------------------------------------------
--
namespace boost
{
//------------------------------------------------------------------------
template <typename T, typename Pointer = boost::shared_ptr<T> >
class serial_ptr
{
private: // Types
enum tag { t_id, t_pointer };
typedef Pointer pointer_type;
typedef char storage_type[sizeof(pointer_type)];
public: // Structors
serial_ptr(int id)
: tag_(t_id) { new (value_) int(id); }
serial_ptr(T* p)
: tag_(t_pointer) { new (value_)
pointer_type(p); }
serial_ptr(pointer_type const& p)
: tag_(t_pointer) { new (value_)
pointer_type(p); }
serial_ptr(serial_ptr const& p)
: tag_(p.tag_)
{
if (tag_ == t_id) new (value_) int(p);
else new (value_) pointer_type(p);
}
~serial_ptr(void)
{
if (tag_ == t_pointer)
{
reinterpret_cast<pointer_type*>(value_)->~pointer_type();
}
}
public: // Operators
serial_ptr& operator=(int id)
{
serial_ptr(id).swap(*this);
return *this;
}
serial_ptr& operator=(pointer_type p)
{
serial_ptr(p).swap(*this);
return *this;
}
serial_ptr& operator=(serial_ptr p)
{
swap(p);
return *this;
}
operator int(void) const
{
if (tag_ != t_id)
{
throw std::runtime_error("Invalid serial_ptr conversion");
}
return *reinterpret_cast<int const*>(value_);
}
operator pointer_type(void) const
{
if (tag_ != t_pointer)
{
throw std::runtime_error("Invalid serial_ptr conversion");
}
return *reinterpret_cast<pointer_type const*>(value_);
}
T* operator->(void) const
{
return operator pointer_type().operator->();
}
void swap(serial_ptr& p)
{
std::swap(tag_, p.tag_);
storage_type Tmp;
std::memcpy(Tmp, value_, sizeof(value_));
std::memcpy(value_, p.value_, sizeof(value_));
std::memcpy(p.value_, Tmp, sizeof(value_));
}
private: // Implementation
tag tag_;
storage_type value_;
};
//------------------------------------------------------------------------
} // namespace boost
Dave