diff options
author | Colin Snover | 2017-11-17 23:28:15 -0600 |
---|---|---|
committer | Eugene Sandulenko | 2017-11-18 22:35:12 +0100 |
commit | 076667dc0064432a3d4e3cf696d6688ee01a17a9 (patch) | |
tree | 1c2c622acc4a660109bf0a8ba22c94e8c4ee1c2c /common | |
parent | 62d6a80c869ee76eeb5abb99b29955399414f71a (diff) | |
download | scummvm-rg350-076667dc0064432a3d4e3cf696d6688ee01a17a9.tar.gz scummvm-rg350-076667dc0064432a3d4e3cf696d6688ee01a17a9.tar.bz2 scummvm-rg350-076667dc0064432a3d4e3cf696d6688ee01a17a9.zip |
COMMON: Add limited support for custom deleters to ScopedPtr
Custom deleters of ScopedPtr are not currently fully conforming to
C++11's support for custom deleters in std::unique_ptr for the
sake of simplicity of implementation. Unlike in the standard
library, plain functions and lvalue references are not supported,
nor may custom deleters be passed to the constructor at runtime.
This can be improved in the future, if necessary, by doing what
standard library implementations usually do and creating a Pair
class that uses the Empty Base Optimization idiom to avoid extra
storage overhead of the deleter instance when it is not needed, as
in typical standard library implementations, plus some additional
type traits to support the necessary metaprogramming for the
different type overloads.
Diffstat (limited to 'common')
-rw-r--r-- | common/ptr.h | 30 |
1 files changed, 16 insertions, 14 deletions
diff --git a/common/ptr.h b/common/ptr.h index 510fec14df..f592beb005 100644 --- a/common/ptr.h +++ b/common/ptr.h @@ -40,12 +40,7 @@ class SharedPtrDeletionImpl : public SharedPtrDeletionInternal { public: SharedPtrDeletionImpl(T *ptr) : _ptr(ptr) {} ~SharedPtrDeletionImpl() { - // Checks if the supplied type is not just a plain - // forward definition, taken from boost::checked_delete - // This makes the user really aware what he tries to do - // when using this with an incomplete type. - typedef char completeCheck[sizeof(T) ? 1 : -1]; - (void)sizeof(completeCheck); + STATIC_ASSERT(sizeof(T) > 0, SharedPtr_cannot_delete_incomplete_type); delete _ptr; } private: @@ -223,8 +218,16 @@ private: PointerType _pointer; }; -template<typename T> -class ScopedPtr : private NonCopyable, public SafeBool<ScopedPtr<T> > { +template <typename T> +struct DefaultDeleter { + inline void operator()(T *object) { + STATIC_ASSERT(sizeof(T) > 0, cannot_delete_incomplete_type); + delete object; + } +}; + +template<typename T, class D = DefaultDeleter<T> > +class ScopedPtr : private NonCopyable, public SafeBool<ScopedPtr<T, D> > { public: typedef T ValueType; typedef T *PointerType; @@ -242,14 +245,14 @@ public: bool operator_bool() const { return _pointer != nullptr; } ~ScopedPtr() { - delete _pointer; + D()(_pointer); } /** * Resets the pointer with the new value. Old object will be destroyed */ void reset(PointerType o = 0) { - delete _pointer; + D()(_pointer); _pointer = o; } @@ -276,9 +279,8 @@ private: PointerType _pointer; }; - -template<typename T> -class DisposablePtr : private NonCopyable, public SafeBool<DisposablePtr<T> > { +template<typename T, class D = DefaultDeleter<T> > +class DisposablePtr : private NonCopyable, public SafeBool<DisposablePtr<T, D> > { public: typedef T ValueType; typedef T *PointerType; @@ -287,7 +289,7 @@ public: explicit DisposablePtr(PointerType o, DisposeAfterUse::Flag dispose) : _pointer(o), _dispose(dispose) {} ~DisposablePtr() { - if (_dispose) delete _pointer; + if (_dispose) D()(_pointer); } ReferenceType operator*() const { return *_pointer; } |