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