diff options
author | Murray Cumming <murrayc@murrayc.com> | 2016-04-10 11:59:00 +0200 |
---|---|---|
committer | Murray Cumming <murrayc@murrayc.com> | 2017-04-07 11:03:48 +0200 |
commit | 62e5b60a7f9c353a5198354ec9ac12b312e326ee (patch) | |
tree | 6e88a353b5bcc19307aae1d6e49a3d4c9b1f882a /glib/glibmm/refptr.h | |
parent | 38cba7e9aaa18e735f7e2ca32b909e92b8d27091 (diff) | |
download | glibmm-62e5b60a7f9c353a5198354ec9ac12b312e326ee.tar.gz |
RefPtr: Make this an alias for shared_ptr<> instead.
Specifying a Deleter in make_refptr_for_instance().
And changing RefPtr::cast_dynamic<>() to std::dynamic_pointer_cast<>().
The glibmm_refptr test then becomes rather silly, and should maybe
just be removed.
Diffstat (limited to 'glib/glibmm/refptr.h')
-rw-r--r-- | glib/glibmm/refptr.h | 464 |
1 files changed, 25 insertions, 439 deletions
diff --git a/glib/glibmm/refptr.h b/glib/glibmm/refptr.h index bdcc9211..eee7f176 100644 --- a/glib/glibmm/refptr.h +++ b/glib/glibmm/refptr.h @@ -20,11 +20,22 @@ #include <glibmmconfig.h> #include <glib.h> -#include <utility> +#include <memory> namespace Glib { +class ObjectBase; + +template <class T_CppObject> +void RefPtrDeleter(T_CppObject* object) +{ + if (!object) + return; + + object->unreference(); +} + /** RefPtr<> is a reference-counting shared smartpointer. * * Some objects in gtkmm are obtained from a shared @@ -49,452 +60,27 @@ namespace Glib * book for further information. */ template <class T_CppObject> -class RefPtr -{ -private: -#ifndef DOXYGEN_SHOULD_SKIP_THIS - /** Helper class for disallowing use of Glib::RefPtr with certain classes. - * - * Disallow for instance in Gtk::Widget and its subclasses. - * Glib::RefPtr<T>::is_allowed_type::value is false if - * T:dont_allow_use_in_glib_refptr_ is a public type, else it's true. - * Example: - * @code - * using dont_allow_use_in_glib_refptr_ = int; - * @endcode - */ - class is_allowed_type - { - private: - struct big - { - int memory[64]; - }; - - static big check(...); - - // If X::dont_allow_use_in_glib_refptr_ is not a type, this check() overload - // is ignored because of the SFINAE rule (Substitution Failure Is Not An Error). - template <typename X> - static typename X::dont_allow_use_in_glib_refptr_ check(X* obj); - - public: - static const bool value = sizeof(check(static_cast<T_CppObject*>(nullptr))) == sizeof(big); - }; - - static_assert(is_allowed_type::value, "Glib::RefPtr must not be used with this class."); -#endif /* DOXYGEN_SHOULD_SKIP_THIS */ - -public: - /** Default constructor - * - * Afterwards it will be null and use of -> will cause a segmentation fault. - */ - inline RefPtr() noexcept; - - /// Destructor - decrements reference count. - inline ~RefPtr() noexcept; - - /// For use only by the \::create() methods. - explicit inline RefPtr(T_CppObject* pCppObject) noexcept; - - /** Copy constructor - * - * This increments the shared reference count. - */ - inline RefPtr(const RefPtr& src) noexcept; - - /** Move constructor - */ - inline RefPtr(RefPtr&& src) noexcept; - - /** Move constructor (from different, but castable type). - */ - template <class T_CastFrom> - inline RefPtr(RefPtr<T_CastFrom>&& src) noexcept; - - /** Copy constructor (from different, but castable type). - * - * Increments the reference count. - */ - template <class T_CastFrom> - inline RefPtr(const RefPtr<T_CastFrom>& src) noexcept; - - /** Swap the contents of two RefPtr<>. - * This method swaps the internal pointers to T_CppObject. This can be - * done safely without involving a reference/unreference cycle and is - * therefore highly efficient. - */ - inline void swap(RefPtr& other) noexcept; - - /// Copy from another RefPtr: - inline RefPtr& operator=(const RefPtr& src) noexcept; - - /// Move assignment operator: - inline RefPtr& operator=(RefPtr&& src) noexcept; - - /// Move assignment operator (from different, but castable type): - template <class T_CastFrom> - inline RefPtr& operator=(RefPtr<T_CastFrom>&& src) noexcept; - - /** Copy from different, but castable type). - * - * Increments the reference count. - */ - template <class T_CastFrom> - inline RefPtr& operator=(const RefPtr<T_CastFrom>& src) noexcept; - - /// Tests whether the RefPtr<> point to the same underlying instance. - inline bool operator==(const RefPtr& src) const noexcept; - - /// See operator==(). - inline bool operator!=(const RefPtr& src) const noexcept; - - /** Dereferencing. - * - * Use the methods of the underlying instance like so: - * <code>refptr->memberfun()</code>. - */ - inline T_CppObject* operator->() const noexcept; - - /** Test whether the RefPtr<> points to any underlying instance. - * - * Mimics usage of ordinary pointers: - * @code - * if (ptr) - * do_something(); - * @endcode - */ - inline explicit operator bool() const noexcept; - - /** Set underlying instance to nullptr, decrementing reference count of existing instance - * appropriately. - * @newin{2,16} - */ - inline void reset() noexcept; - - /** Release the ownership of underlying instance. - * - * RefPtr's underlying instance is set to nullptr, therefore underlying object can't be accessed - * through this RefPtr anymore. - * @return an underlying instance. - * - * Most users should not use release(). It can spoil the automatic destruction - * of the managed object. A legitimate use is if you immediately give RefPtr's - * reference to another object. - */ - inline T_CppObject* release() noexcept G_GNUC_WARN_UNUSED_RESULT; - - /** Dynamic cast to derived class. - * - * The RefPtr can't be cast with the usual notation so instead you can use - * @code - * ptr_derived = RefPtr<Derived>::cast_dynamic(ptr_base); - * @endcode - */ - template <class T_CastFrom> - static inline RefPtr cast_dynamic(const RefPtr<T_CastFrom>& src) noexcept; - - /** Static cast to derived class. - * - * Like the dynamic cast; the notation is - * @code - * ptr_derived = RefPtr<Derived>::cast_static(ptr_base); - * @endcode - */ - template <class T_CastFrom> - static inline RefPtr cast_static(const RefPtr<T_CastFrom>& src) noexcept; - - /** Cast to non-const. - * - * The RefPtr can't be cast with the usual notation so instead you can use - * @code - * ptr_unconst = RefPtr<UnConstType>::cast_const(ptr_const); - * @endcode - */ - template <class T_CastFrom> - static inline RefPtr cast_const(const RefPtr<T_CastFrom>& src) noexcept; - - /** Compare based on the underlying instance address. - * - * This is needed in code that requires an ordering on - * RefPtr<T_CppObject> instances, e.g. std::set<RefPtr<T_CppObject> >. - * - * Without these, comparing two RefPtr<T_CppObject> instances - * is still syntactically possible, but the result is semantically - * wrong, as p1 REL_OP p2 is interpreted as (bool)p1 REL_OP (bool)p2. - */ - inline bool operator<(const RefPtr& src) const noexcept; - - /// See operator<(). - inline bool operator<=(const RefPtr& src) const noexcept; - - /// See operator<(). - inline bool operator>(const RefPtr& src) const noexcept; - - /// See operator<(). - inline bool operator>=(const RefPtr& src) const noexcept; - -private: - T_CppObject* pCppObject_; -}; - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - -// RefPtr<>::operator->() comes first here since it's used by other methods. -// If it would come after them it wouldn't be inlined. - -template <class T_CppObject> -inline T_CppObject* RefPtr<T_CppObject>::operator->() const noexcept -{ - return pCppObject_; -} - -template <class T_CppObject> -inline RefPtr<T_CppObject>::RefPtr() noexcept : pCppObject_(nullptr) -{ -} - -template <class T_CppObject> -inline RefPtr<T_CppObject>::~RefPtr() noexcept -{ - if (pCppObject_) - pCppObject_->unreference(); // This could cause pCppObject to be deleted. -} - -template <class T_CppObject> -inline RefPtr<T_CppObject>::RefPtr(T_CppObject* pCppObject) noexcept : pCppObject_(pCppObject) -{ -} - -template <class T_CppObject> -inline RefPtr<T_CppObject>::RefPtr(const RefPtr& src) noexcept : pCppObject_(src.pCppObject_) -{ - if (pCppObject_) - pCppObject_->reference(); -} - -template <class T_CppObject> -inline RefPtr<T_CppObject>::RefPtr(RefPtr&& src) noexcept : pCppObject_(src.pCppObject_) -{ - src.pCppObject_ = nullptr; -} - -template <class T_CppObject> -template <class T_CastFrom> -inline RefPtr<T_CppObject>::RefPtr(RefPtr<T_CastFrom>&& src) noexcept : pCppObject_(src.release()) -{ -} - -// The templated ctor allows copy construction from any object that's -// castable. Thus, it does downcasts: -// base_ref = derived_ref -template <class T_CppObject> -template <class T_CastFrom> -inline RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CastFrom>& src) noexcept : - // A different RefPtr<> will not allow us access to pCppObject_. We need - // to add a get_underlying() for this, but that would encourage incorrect - // use, so we use the less well-known operator->() accessor: - pCppObject_(src.operator->()) -{ - if (pCppObject_) - pCppObject_->reference(); -} - -template <class T_CppObject> -inline void -RefPtr<T_CppObject>::swap(RefPtr& other) noexcept -{ - T_CppObject* const temp = pCppObject_; - pCppObject_ = other.pCppObject_; - other.pCppObject_ = temp; -} - -template <class T_CppObject> -inline RefPtr<T_CppObject>& -RefPtr<T_CppObject>::operator=(const RefPtr& src) noexcept -{ - // In case you haven't seen the swap() technique to implement copy - // assignment before, here's what it does: - // - // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby - // increasing the reference count of the source object. - // - // 2) Swap the internal object pointers of *this and the temporary - // RefPtr<>. After this step, *this already contains the new pointer, - // and the old pointer is now managed by temp. - // - // 3) The destructor of temp is executed, thereby unreferencing the - // old object pointer. - // - // This technique is described in Herb Sutter's "Exceptional C++", and - // has a number of advantages over conventional approaches: - // - // - Code reuse by calling the copy ctor. - // - Strong exception safety for free. - // - Self assignment is handled implicitely. - // - Simplicity. - // - It just works and is hard to get wrong; i.e. you can use it without - // even thinking about it to implement copy assignment whereever the - // object data is managed indirectly via a pointer, which is very common. - - RefPtr<T_CppObject> temp(src); - this->swap(temp); - return *this; -} - -template <class T_CppObject> -inline RefPtr<T_CppObject>& -RefPtr<T_CppObject>::operator=(RefPtr&& src) noexcept -{ - RefPtr<T_CppObject> temp(std::move(src)); - this->swap(temp); - src.pCppObject_ = nullptr; - - return *this; -} - -template <class T_CppObject> -template <class T_CastFrom> -inline RefPtr<T_CppObject>& -RefPtr<T_CppObject>::operator=(RefPtr<T_CastFrom>&& src) noexcept -{ - if (pCppObject_) - pCppObject_->unreference(); - pCppObject_ = src.release(); - - return *this; -} - -template <class T_CppObject> -template <class T_CastFrom> -inline RefPtr<T_CppObject>& -RefPtr<T_CppObject>::operator=(const RefPtr<T_CastFrom>& src) noexcept -{ - RefPtr<T_CppObject> temp(src); - this->swap(temp); - return *this; -} - -template <class T_CppObject> -inline bool -RefPtr<T_CppObject>::operator==(const RefPtr& src) const noexcept -{ - return (pCppObject_ == src.pCppObject_); -} - -template <class T_CppObject> -inline bool -RefPtr<T_CppObject>::operator!=(const RefPtr& src) const noexcept -{ - return (pCppObject_ != src.pCppObject_); -} - -template <class T_CppObject> -inline RefPtr<T_CppObject>::operator bool() const noexcept -{ - return (pCppObject_ != nullptr); -} - -template <class T_CppObject> -inline void -RefPtr<T_CppObject>::reset() noexcept -{ - RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this - this->swap(temp); -} - -template <class T_CppObject> -inline T_CppObject* -RefPtr<T_CppObject>::release() noexcept -{ - T_CppObject* tmp = pCppObject_; - pCppObject_ = nullptr; - return tmp; -} - -template <class T_CppObject> -template <class T_CastFrom> -inline RefPtr<T_CppObject> -RefPtr<T_CppObject>::cast_dynamic(const RefPtr<T_CastFrom>& src) noexcept -{ - T_CppObject* const pCppObject = dynamic_cast<T_CppObject*>(src.operator->()); - - if (pCppObject) - pCppObject->reference(); - - return RefPtr<T_CppObject>(pCppObject); -} - -template <class T_CppObject> -template <class T_CastFrom> -inline RefPtr<T_CppObject> -RefPtr<T_CppObject>::cast_static(const RefPtr<T_CastFrom>& src) noexcept -{ - T_CppObject* const pCppObject = static_cast<T_CppObject*>(src.operator->()); - - if (pCppObject) - pCppObject->reference(); - - return RefPtr<T_CppObject>(pCppObject); -} - -template <class T_CppObject> -template <class T_CastFrom> -inline RefPtr<T_CppObject> -RefPtr<T_CppObject>::cast_const(const RefPtr<T_CastFrom>& src) noexcept -{ - T_CppObject* const pCppObject = const_cast<T_CppObject*>(src.operator->()); - - if (pCppObject) - pCppObject->reference(); - - return RefPtr<T_CppObject>(pCppObject); -} - -template <class T_CppObject> -inline bool -RefPtr<T_CppObject>::operator<(const RefPtr& src) const noexcept -{ - return (pCppObject_ < src.pCppObject_); -} - -template <class T_CppObject> -inline bool -RefPtr<T_CppObject>::operator<=(const RefPtr& src) const noexcept -{ - return (pCppObject_ <= src.pCppObject_); -} +using RefPtr = std::shared_ptr<T_CppObject>; -template <class T_CppObject> -inline bool -RefPtr<T_CppObject>::operator>(const RefPtr& src) const noexcept -{ - return (pCppObject_ > src.pCppObject_); -} - -template <class T_CppObject> -inline bool -RefPtr<T_CppObject>::operator>=(const RefPtr& src) const noexcept -{ - return (pCppObject_ >= src.pCppObject_); -} - -#endif /* DOXYGEN_SHOULD_SKIP_THIS */ - -/** @relates Glib::RefPtr */ -template <class T_CppObject> -inline void -swap(RefPtr<T_CppObject>& lhs, RefPtr<T_CppObject>& rhs) noexcept +/** This would not be useful, + * because application code should not new these objects anyway. + * And it is not useful inside glibmm or gtkmm code because + * the constructors are protected, so can't be called from this utilility + * function. + * +template <class T_CppObject, class... T_Arg> +RefPtr<T_CppObject> +make_refptr(T_Arg... arg) { - lhs.swap(rhs); + return RefPtr<T_CppObject>(new T_CppObject(arg...)); } +*/ template <class T_CppObject> RefPtr<T_CppObject> make_refptr_for_instance(T_CppObject* object) { - return RefPtr<T_CppObject>(object); + return RefPtr<T_CppObject>(object, &RefPtrDeleter<T_CppObject>); } } // namespace Glib |