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




_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Reply via email to