Boost logo

Boost :

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

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk