Deep Copyを行うポインタ
深いコピーを行うポインタ。
使うかどうか分かんないけど、参考にしたソースの通り、pimplには使えるかも。
深いコピーに合わせて深い比較(deep comparison)も行います。
型はCopyConstructibleで。
完全型云々辺りはよく分からないのでもう少し調べてみよう。
Custom Deleterには未対応。
deep_copy_ptr.hpp
// Deep copy/compare Pointer #ifndef HWM_DEEPCOPYPTR_HPP_ #define HWM_DEEPCOPYPTR_HPP_ #include <memory> #include <boost/assert.hpp> #include <boost/noncopyable.hpp> namespace hwm { namespace detail { class deep_copy_ptr_holder_base : boost::noncopyable { public: virtual ~deep_copy_ptr_holder_base () {} virtual std::auto_ptr<deep_copy_ptr_holder_base> clone () const = 0; virtual void* get_ptr () = 0; virtual const void* get_ptr () const = 0; }; template <class T> class deep_copy_ptr_holder : public deep_copy_ptr_holder_base { typedef deep_copy_ptr_holder this_type; typedef deep_copy_ptr_holder_base base_type; std::auto_ptr<T> ptr_; public: explicit this_type (T* ptr) : ptr_(ptr) {} explicit this_type (std::auto_ptr<T> p) : ptr_(p) {} std::auto_ptr<T> clone_detail() const { return (ptr_.get()) ? std::auto_ptr<T>( new T(*ptr_) ) : std::auto_ptr<T>(); } virtual std::auto_ptr<base_type> clone () const { return std::auto_ptr<base_type>(new this_type(clone_detail())); } virtual void* get_ptr () { return ptr_.get(); } virtual const void* get_ptr () const { return ptr_.get(); } }; } //namespace detail template <class T> class deep_copy_ptr { private: typedef void (deep_copy_ptr::*bool_type)() const; void bool_func () const {} std::auto_ptr<detail::deep_copy_ptr_holder_base> holder_; public: deep_copy_ptr () : holder_(new detail::deep_copy_ptr_holder<T>(0)) {} template<typename Y> explicit deep_copy_ptr (Y* p) : holder_(new detail::deep_copy_ptr_holder<T>(std::auto_ptr<T>(p))) {} template<typename Y> explicit deep_copy_ptr (std::auto_ptr<Y> p) : holder_(new detail::deep_copy_ptr_holder<T>(p)) {} deep_copy_ptr (const deep_copy_ptr& rhs) : holder_(rhs.holder_->clone()) {} template<typename Y> explicit deep_copy_ptr (const deep_copy_ptr<Y>& rhs) : holder_(rhs.holder_->clone()) {} deep_copy_ptr & operator = (const deep_copy_ptr& rhs) { BOOST_ASSERT(rhs.holder_.get()); deep_copy_ptr<T> tmp(rhs); this->swap(tmp); return *this; } void swap (deep_copy_ptr &rhs) { std::swap(holder_, rhs.holder_); } operator bool_type () const { BOOST_ASSERT(holder_.get()); return (holder_->get_ptr()) ? &deep_copy_ptr::bool_func : 0; } template<typename Y> void reset (Y* p = 0) { deep_copy_ptr tmp(p); swap(tmp); } T * get () { BOOST_ASSERT(holder_.get()); return static_cast<T *>(holder_->get_ptr()); } T const * get () const { BOOST_ASSERT(holder_.get()); return static_cast<T const *>(holder_->get_ptr()); } T * operator -> () { return get(); } T const * operator -> () const { return get(); } T & operator * () { return *get(); } T const & operator * () const { return *get(); } template<typename Y> bool operator== (Y const *p) const { BOOST_ASSERT(holder_.get()); return (get() == p) || ( (get() && p) ? *get() == *p : false ); } template<typename Y> bool operator!= (Y const *p) const { return !((*this) == p); } template<typename Y> bool operator== (deep_copy_ptr<Y> const &r) const { return (*this) == r.get(); } template<typename Y> bool operator!= (deep_copy_ptr<Y> const &r) const { return (*this) != r.get(); } }; template<typename T> void swap(deep_copy_ptr<T> &lhs, deep_copy_ptr<T> &rhs) { lhs.swap(rhs); } template<typename T, typename U> bool operator==(T const *t, deep_copy_ptr<U> const &u) { return u == t; } template<typename T, typename U> bool operator!=(T const *t, deep_copy_ptr<U> const &u) { return u != t; } } //namespace hwm #endif //HWM_DEEPCOPYPTR_HPP_
テスト
#include <iostream> #include <string> #include <boost/test/minimal.hpp> #include <boost/current_function.hpp> #include "deep_copy_ptr.hpp" struct A { int i; char c; A() : i(0) , c(0) { std::cout << BOOST_CURRENT_FUNCTION << std::endl; } A(A const &a) : i(a.i) , c(a.c) { std::cout << BOOST_CURRENT_FUNCTION << std::endl; } A& operator= (A const &a) { std::cout << BOOST_CURRENT_FUNCTION << std::endl; i = a.i; c = a.c; return *this; } virtual void foo() = 0; }; struct B : public A { std::string s; B() { std::cout << BOOST_CURRENT_FUNCTION << std::endl; } B(B const &b) : A(b) , s(b.s) { std::cout << BOOST_CURRENT_FUNCTION << std::endl; } B& operator= (B const &b) { std::cout << BOOST_CURRENT_FUNCTION << std::endl; static_cast<A &>(*this) = static_cast<A const &>(b); s = b.s; return *this } bool operator==(B const &b) const { return i == b.i && c == b.c && s == b.s; } void foo() {} }; struct C { B b; C() { std::cout << BOOST_CURRENT_FUNCTION << std::endl; } C(C const &c) : b(c.b) { std::cout << BOOST_CURRENT_FUNCTION << std::endl; } C& operator= (C const &c) { std::cout << BOOST_CURRENT_FUNCTION << std::endl; b = c.b; return *this; } }; struct D { hwm::deep_copy_ptr<C> c; D() : c(new C) { std::cout << BOOST_CURRENT_FUNCTION << std::endl; } D(D const &d) : c(new C(*d.c)) { std::cout << BOOST_CURRENT_FUNCTION << std::endl; } D& operator=(D const &d) { std::cout << BOOST_CURRENT_FUNCTION << std::endl; c = d.c; return *this; } }; class E { public: hwm::deep_copy_ptr<D> d; E() : d(new D()) { std::cout << BOOST_CURRENT_FUNCTION << std::endl; } ~E() { std::cout << BOOST_CURRENT_FUNCTION << std::endl; } E(E const &e) : d(new D(*e.d)) { std::cout << BOOST_CURRENT_FUNCTION << std::endl; } E& operator=(E const &e) { std::cout << BOOST_CURRENT_FUNCTION << std::endl; d = e.d; return *this; } void bar(D const &new_d) { hwm::deep_copy_ptr<D> tmp(new D(new_d)); swap(d, tmp); } }; int test_main(int argc, char **argv) { D d1; d1.c->b.s = "test"; d1.c->b.i = 100; d1.c->b.c = 'X'; D d2 = d1; d2.c->b.c = 'Y'; BOOST_CHECK(d1.c->b.s == d2.c->b.s); BOOST_CHECK(d1.c->b.i == d2.c->b.i); BOOST_CHECK(d1.c->b.c != d2.c->b.c); E e1; E e2; e1.bar( d1 ); e2 = e1; BOOST_CHECK(e1.d->c->b.s == e2.d->c->b.s); hwm::deep_copy_ptr<D> d3(new D); BOOST_CHECK(d3); hwm::deep_copy_ptr<D> d4 = d3; BOOST_CHECK(d4); hwm::deep_copy_ptr<D>().swap(d4); BOOST_CHECK(!d4); BOOST_CHECK(d4 == false); BOOST_CHECK(d4 == NULL); //hwm::deep_copy_ptr<A> a; //compilation error hwm::deep_copy_ptr<B> b1; hwm::deep_copy_ptr<B> b2(new B); hwm::deep_copy_ptr<B> b3(new B); hwm::deep_copy_ptr<C> c(new C); BOOST_CHECK(b1 != b2); //deep comparison BOOST_CHECK(b2 == b3); //b2 == c; //complation error ;-) return 0; }
参考 :
The Safe Bool Idiom
http://zakio.net/blog/2009/04/15-222117.html
使う・・・かなぁ?