Skip to content

Instantly share code, notes, and snippets.

@ubnt-intrepid
Last active August 29, 2015 14:12
Show Gist options
  • Save ubnt-intrepid/4747fccfd2fde16b2cb4 to your computer and use it in GitHub Desktop.
Save ubnt-intrepid/4747fccfd2fde16b2cb4 to your computer and use it in GitHub Desktop.
unique_ptrにコピーコンストラクタ+コピー代入演算子を追加してみる
#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;
@ubnt-intrepid
Copy link
Author

boost::optionalでもいいと思う

@ubnt-intrepid
Copy link
Author

TODO: friendにする

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment