Last active
August 29, 2015 14:12
-
-
Save ubnt-intrepid/4747fccfd2fde16b2cb4 to your computer and use it in GitHub Desktop.
unique_ptrにコピーコンストラクタ+コピー代入演算子を追加してみる
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <memory> // std::unique_ptr<T, D> | |
#if (__cplusplus < 201103) | |
# if defined(_MSC_VER) // ..., VC10.0, VC11.0, VC12.0 | |
# define noexcept _NOEXCEPT | |
# endif | |
#endif | |
namespace std { | |
// コピー操作を定義したunique_ptr (deep copy) | |
// ポインタのコピー操作時に格納しているインスタンスのコピーを実行する | |
// (すなわちコピー後に格納されているインスタンスは元のインスタンスとは異なる) | |
// コピーするのは格納しているインスタンスのみであり,そのインスタンスに対する | |
// deep copyは保証されないことに注意 | |
// Usage: | |
// ・基本的にはstd::unique_ptr<T, D>と同じように使用可能 | |
// | |
// { | |
// util::deep_ptr<foo> ptr = util::make_unique<int>("args"); | |
// | |
// std::cout << *ptr << std::endl; | |
// auto b = ptr->getValue(); | |
// | |
// util::deep_ptr<foo> ptr1 = ptr; // インスタンスがコピーされる | |
// util::deep_ptr<foo> ptr2 = std::move(ptr1); // 所有権が譲渡される(ptr1は使用不可能) | |
// | |
// } // foo::~foo(); | |
// | |
template <typename T, typename D = std::default_delete<T>> | |
class deep_ptr | |
{ | |
typedef deep_ptr<T, D> self_type; | |
typedef unique_ptr<T, D> body_type; | |
body_type body; | |
public: | |
typedef typename unique_ptr<T, D>::element_type element_type; | |
typedef typename unique_ptr<T, D>::deleter_type deleter_type; | |
typedef typename unique_ptr<T, D>::pointer pointer; | |
public: | |
// constructor() | |
deep_ptr() noexcept = default; | |
explicit deep_ptr(pointer p) noexcept | |
: body(p) {} | |
deep_ptr(pointer p, deleter_type const& d1) noexcept | |
: body(p, d1) {} | |
deep_ptr(pointer p, deleter_type && d2) noexcept | |
: body(p, d2) {} | |
deep_ptr(self_type && src) noexcept | |
: body(src.body) {} | |
deep_ptr(nullptr_t) noexcept | |
: body(nullptr_t()) {} | |
template <typename U, typename E> | |
deep_ptr(deep_ptr<U, E> && u) noexcept | |
: body(u.body) {} | |
template <typename U> | |
deep_ptr(auto_ptr<U>&& u) noexcept | |
: body(u) {} | |
// destructor() | |
~deep_ptr() {} | |
// assignment operators | |
self_type& operator=(self_type && u) noexcept { | |
body = u.body; | |
return *this; | |
} | |
template <typename U, typename E> | |
self_type& operator=(deep_ptr<U, E> && u) noexcept { | |
body = u.body; | |
return *this; | |
} | |
self_type& operator=(nullptr_t) noexcept { | |
body = nullptr_t(); | |
return *this; | |
} | |
pointer release() noexcept{ | |
return body.release(); | |
} | |
void reset(pointer p = pointer()) noexcept { | |
body.reset(p); | |
} | |
void swap(self_type& x) noexcept { | |
body.swap(x.body); | |
} | |
pointer get() const noexcept { | |
return body.get(); | |
} | |
deleter_type & get_deleter() noexcept { return body.get_deleter(); } | |
deleter_type const& get_deleter() const noexcept { return body.get_deleter(); } | |
explicit operator bool() const noexcept { | |
return body.operator bool(); | |
} | |
// 単一オブジェクト版only | |
typename std::add_lvalue_reference<T>::type operator*() const { | |
return body.operator*(); | |
} | |
pointer operator->() const noexcept { return body.operator->(); } | |
// 配列版only | |
//T& operator[](size_t i) const; | |
#define BINARY_OPERATOR_DEF(OP) \ | |
template <typename T1, typename D1, typename T2, typename D2> \ | |
friend bool operator OP(deep_ptr<T1, D1> const& a, deep_ptr<T2, D2> const& b) \ | |
{ \ | |
return a.body OP b.body; \ | |
} \ | |
template <typename T, typename D> \ | |
friend bool operator OP(deep_ptr<T, D> const& x, nullptr_t) noexcept \ | |
{ \ | |
return x.body OP std::nullptr_t(); \ | |
} \ | |
template <typename T, typename D> \ | |
friend bool operator OP(nullptr_t, deep_ptr<T, D> const& x) noexcept \ | |
{ \ | |
return std::nullptr_t OP x.body; \ | |
} | |
BINARY_OPERATOR_DEF(==) | |
BINARY_OPERATOR_DEF(!=) | |
BINARY_OPERATOR_DEF(>) | |
BINARY_OPERATOR_DEF(>=) | |
BINARY_OPERATOR_DEF(<) | |
BINARY_OPERATOR_DEF(<=) | |
template <typename T, typename D> | |
friend void swap(deep_ptr<T, D> & a, deep_ptr<T, D> & b) noexcept { | |
a.body.swap(b.body); // noexcept | |
} | |
#undef BINARY_OPERATOR_DEF | |
public: | |
// deep_ptr特有の機能 | |
// copy constructor & assignment operator | |
deep_ptr(self_type const& src) { | |
pointer p = new element_type(*src.body); | |
this->body = body_type(p); // noexcept | |
} | |
deep_ptr(self_type const& src, deleter_type const& d1) { | |
pointer p = new element_type(*src.body); | |
this->body = body_type(p, d1); // noexcept | |
} | |
deep_ptr(self_type const& src, deleter_type && d2) { | |
pointer p = new element_type(*src.body); | |
this->body = body_type(p, d2); // noexcept | |
} | |
template <typename U, typename E> | |
self_type& operator=(deep_ptr<U, E> const& u) { | |
U* p = new U(*u.body); | |
E e = u.get_deleter(); // deleterをコピー | |
this->body = unique_ptr<U, E>(p, std::move(e)); // noexcept | |
return *this; | |
} | |
}; | |
#if _MSC_VER < 1900 | |
// Variadic Templateが使用できない場合 | |
#else | |
template <typename T, typename... Args> | |
deep_ptr<T> make_deep(Args && ...args) { | |
return deep_ptr<T>(make_unique<T>(forward(args...))); | |
} | |
#endif | |
}// namespace std; |
TODO: friendにする
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
boost::optionalでもいいと思う