Deleter を取る scoped_ptr

クラステンプレートの引数で deleter を取るものであれば、boost::interprocess::scoped_ptr があります。今回は、コンストラクタテンプレートの引数で deleter を取るものを C++0x で書いてみました。
GCC 4.6 で入った新機能 noexcept, nullptr も使っています (使ってみたかっただけとも言う)。

#include <cstddef>
#include <functional>
#include <memory>
#include <type_traits>
#include <utility>

template <class T>
class scoped_ptr
{
public:
    typedef T element_type;

    scoped_ptr() noexcept
      : ptr(nullptr), del()
    {}

    template <class Y>
    explicit scoped_ptr(Y *p)
      : ptr(p), del(std::bind(std::default_delete<Y>(), p))
    {}

    template <class Y, class D>
    scoped_ptr(Y *p, D d)
      : ptr(p), del(std::bind(d, p))
    {}

    /*
    template <class Y, class D, class A>
    scoped_ptr(Y *p, D d, A a)
      : ptr(p), del(std::allocator_arg, a, std::bind(d, p))
    {}
    */

    template <class D>
    scoped_ptr(std::nullptr_t p, D d)
      : ptr(p), del(std::bind(d, p))
    {}

    /*
    template <class D, class A>
    scoped_ptr(std::nullptr_t p, D d, A a)
      : ptr(p), del(std::allocator_arg, a, std::bind(d, p))
    {}
    */

    template <class Y, class D>
    scoped_ptr(std::unique_ptr<Y, D> &&r)
      : ptr(r.get()), del()
    {
        create_from_unique_ptr(std::move(r));
        r.release();
    }

    scoped_ptr(std::nullptr_t) noexcept
      : ptr(nullptr), del()
    {}

    ~scoped_ptr()
    {
        if (del)
            del();
    }

    void swap(scoped_ptr &r) noexcept
    {
        std::swap(ptr, r.ptr);
        del.swap(r.del);
    }

    void reset() noexcept
    {
        scoped_ptr().swap(*this);
    }

    template <class Y>
    void reset(Y *p)
    {
        scoped_ptr(p).swap(*this);
    }

    template <class Y, class D>
    void reset(Y *p, D d)
    {
        scoped_ptr(p, d).swap(*this);
    }

    /*
    template <class Y, class D, class A>
    void reset(Y *p, D d, A a)
    {
        scoped_ptr(p, d, a).swap(*this);
    }
    */

    T *release()
    {
        T *tmp = ptr;
        ptr = nullptr;
        del = nullptr;
        return tmp;
    }

    T *get() const noexcept
    {
        return ptr;
    }

    T &operator*() const noexcept
    {
        return *ptr;
    }

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

    explicit operator bool() const noexcept
    {
        return ptr != nullptr;
    }

    scoped_ptr(scoped_ptr const &) = delete;

    scoped_ptr &operator=(scoped_ptr const &) = delete;

private:
    template <class Y, class D>
    void create_from_unique_ptr(std::unique_ptr<Y, D> &&r,
        typename std::enable_if<!std::is_reference<D>::value>::type * = 0)
    {
        del = std::bind(r.get_deleter(), r.get());
    }

    template <class Y, class D>
    void create_from_unique_ptr(std::unique_ptr<Y, D> &&r,
        typename std::enable_if<std::is_reference<D>::value>::type * = 0)
    {
        del = std::bind(std::ref(r.get_deleter()), r.get());
    }

    T *ptr;
    std::function<void ()> del;
};

template <class T>
void swap(scoped_ptr<T> &a, scoped_ptr<T> &b)
{
    a.swap(b);
}

shared_ptr と速度がそれほど変わらないので、存在意義などあんまりないです。Copy / move を明示的に禁止できるのが唯一の利点でしょうか。
一応 C++03 版も書いたので置いておきます。http://ideone.com/eTUGF