Boost logo

Boost :

From: Daniel Wallin (dalwan01_at_[hidden])
Date: 2004-01-20 19:06:09


I'm moving this to a new thread.

Not every smart pointer has to handle every possible case. If you want
custom deleters, use shared_ptr<>. The extra storage needed for the
deleter IMO just isn't justified for something as simple as an ownership
transfer utility. What I do find interesting though is the ability to
delete incomplete types, IOW at some level capture of type at
construction.

I'm attaching the implementation that I believe should be pushed
further.

-- 
Daniel Wallin

// Copyright Daniel Wallin 2004. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Based on auto_ptr<> implementation by Rani Sharoni.

#ifndef BOOST_MOVE_PTR_HPP
#define BOOST_MOVE_PTR_HPP

#include <algorithm>

namespace boost {

    template<class T>
    struct move_source
    {
        move_source(T& x) : source(x) {}
        T& source;

    private:
        move_source(T const&);
    };

    template<class T>
    move_source<T> move(T& x)
    {
        return move_source<T>(x);
    }

    template<class T>
    class move_ptr
    {
    public:
        move_ptr() : m_p(0) {}
       
        move_ptr(const move_ptr& p)
            : m_p(const_cast<move_ptr&>(p).release())
        {
        }

        template<class U>
        move_ptr(const move_ptr<U>& p)
            : m_p(const_cast<move_ptr<U>&>(p).release())
        {
            delete_fn = &delete_aux::delete_;
        }

        template<class U>
        move_ptr(move_source<move_ptr<U> > x)
            : m_p(x.source.release())
        {
            delete_fn = &delete_aux::delete_;
        }

        explicit move_ptr(T* p) : m_p(p)
        {
            delete_fn = &delete_aux::delete_;
        }

        ~move_ptr()
        {
            if (m_p) delete_fn(m_p);
        }

        move_ptr& operator=(move_ptr p)
        {
            p.swap(*this);
            return *this;
        }

        T* release()
        {
            T* p = m_p;
            m_p = 0;
            return p;
        }

        void reset(T* p = 0)
        {
            move_ptr(p).swap(*this);
        }

        void swap(move_ptr& p)
        {
            std::swap(m_p, p.m_p);
        }

        T& operator*() const
        {
            return *m_p;
        }

        T* get() const
        {
            return m_p;
        }

        T* operator->() const
        {
            return m_p;
        }

        struct implementation_detail { bool b; };
        typedef bool implementation_detail::*safe_bool_type;

        operator safe_bool_type() const
        {
            return m_p ? &implementation_detail::b : 0;
        }
        
    private:
        template<class U>
        struct cant_move_from_const;

        template<class U>
        struct cant_move_from_const<const move_ptr<U> >
        {
            typedef typename move_ptr<U>::error type;
        };

        template<class U>
        move_ptr(U&, typename cant_move_from_const<U>::type = 0);

        move_ptr(move_ptr&);
        template<class U> move_ptr(move_ptr<U>&);

        struct delete_aux
        {
            static void delete_(T* p) { delete p; }
        };

        typedef void(*delete_fn_t)(T*);

        T* m_p;
        static delete_fn_t delete_fn;
    };

    template<class T>
    typename move_ptr<T>::delete_fn_t move_ptr<T>::delete_fn = 0;

} // namespace boost

#endif // BOOST_MOVE_PTR_HPP


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