X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fsupport%2Fcopied_ptr.h;h=15ef7551e3be0356e273b093941c7690b9df815c;hb=52072b9b4e88e3260637b654d364193092d04192;hp=0683158d811a35b3934b2e4c9a3255446b2a5d85;hpb=d55d4b9c1c99488e37cbe383d5ff6cfa51c77254;p=lyx.git diff --git a/src/support/copied_ptr.h b/src/support/copied_ptr.h index 0683158d81..15ef7551e3 100644 --- a/src/support/copied_ptr.h +++ b/src/support/copied_ptr.h @@ -4,15 +4,21 @@ * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * - * \author Yonat Sharon http://ootips.org/yonat/ + * \author Angus Leeming * - * simple copy-on-create/assign pointer. + * A templated class that can serve as a pointer to an object, with the + * property that when the copied_ptr is copied, it creates its own copy + * of the object pointed to as well. * - * Note: If the actual object pointed to belongs to a derived class, - * then copied_ptr will not create a copy of the derived class object, - * but a new base class object. - * If you want to use a polymorphic copy-on-assign pointer, use - * cloned_ptr. + * The implementation was based originally on Yonat Sharon's copied_ptr templated + * class, as described at http://ootips.org/yonat/, but has evolved toward's + * Herb Sutter's HolderPtr, as described at http://www.gotw.ca/gotw/062.htm. + * (Note, HolderPtr became ValuePtr in his book, More Exceptional C++.) + * + * Warning: if the class stores 'Base * ptr_', but the actual object pointed to + * belongs to a derived class, then you must specialise memory_traits so that + * its clone and destroy member functions do the right thing. Otherwise, you'll + * end up slicing the data. */ #ifndef COPIED_PTR_H @@ -22,11 +28,18 @@ namespace lyx { namespace support { template +struct memory_traits { + static T * clone(T const * ptr) { return new T(*ptr); } + static void destroy(T * ptr) { delete ptr; } +}; + + +template > class copied_ptr { public: explicit copied_ptr(T * = 0); - ~copied_ptr(); copied_ptr(copied_ptr const &); + ~copied_ptr(); copied_ptr & operator=(copied_ptr const &); T & operator*() const; @@ -35,68 +48,59 @@ public: private: T * ptr_; - void copy(copied_ptr const &); }; -template -copied_ptr::copied_ptr(T * p) +template +copied_ptr::copied_ptr(T * p) : ptr_(p) {} -template -copied_ptr::~copied_ptr() -{ - delete ptr_; -} +template +copied_ptr::copied_ptr(copied_ptr const & other) + : ptr_(other.ptr_ ? Traits::clone(other.ptr_) : 0) +{} -template -copied_ptr::copied_ptr(copied_ptr const & other) +template +copied_ptr::~copied_ptr() { - copy(other.get()); + Traits::destroy(ptr_); } -template -copied_ptr & copied_ptr::operator=(copied_ptr const & other) +template +copied_ptr & copied_ptr::operator=(copied_ptr const & other) { - if (&other != this) { - delete ptr_; - copy(other); - } - return *this; + if (&other != this) { + copied_ptr temp(other); + std::swap(ptr_, temp.ptr_); + } + return *this; } -template -T & copied_ptr::operator*() const +template +T & copied_ptr::operator*() const { return *ptr_; } -template -T * copied_ptr::operator->() const +template +T * copied_ptr::operator->() const { return ptr_; } -template -T * copied_ptr::get() const +template +T * copied_ptr::get() const { return ptr_; } - -template -void copied_ptr::copy(copied_ptr const & other) -{ - ptr_ = other.ptr_ ? new T(*other.ptr_) : 0; -} - } // namespace support } // namespace lyx