From 62e5b60a7f9c353a5198354ec9ac12b312e326ee Mon Sep 17 00:00:00 2001 From: Murray Cumming Date: Sun, 10 Apr 2016 11:59:00 +0200 Subject: 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. --- glib/glibmm/refptr.h | 464 +++------------------------------------------------ 1 file changed, 25 insertions(+), 439 deletions(-) (limited to 'glib/glibmm/refptr.h') 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 #include -#include +#include namespace Glib { +class ObjectBase; + +template +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 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::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 - static typename X::dont_allow_use_in_glib_refptr_ check(X* obj); - - public: - static const bool value = sizeof(check(static_cast(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 - inline RefPtr(RefPtr&& src) noexcept; - - /** Copy constructor (from different, but castable type). - * - * Increments the reference count. - */ - template - inline RefPtr(const RefPtr& 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 - inline RefPtr& operator=(RefPtr&& src) noexcept; - - /** Copy from different, but castable type). - * - * Increments the reference count. - */ - template - inline RefPtr& operator=(const RefPtr& 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: - * refptr->memberfun(). - */ - 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::cast_dynamic(ptr_base); - * @endcode - */ - template - static inline RefPtr cast_dynamic(const RefPtr& src) noexcept; - - /** Static cast to derived class. - * - * Like the dynamic cast; the notation is - * @code - * ptr_derived = RefPtr::cast_static(ptr_base); - * @endcode - */ - template - static inline RefPtr cast_static(const RefPtr& 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::cast_const(ptr_const); - * @endcode - */ - template - static inline RefPtr cast_const(const RefPtr& src) noexcept; - - /** Compare based on the underlying instance address. - * - * This is needed in code that requires an ordering on - * RefPtr instances, e.g. std::set >. - * - * Without these, comparing two RefPtr 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 -inline T_CppObject* RefPtr::operator->() const noexcept -{ - return pCppObject_; -} - -template -inline RefPtr::RefPtr() noexcept : pCppObject_(nullptr) -{ -} - -template -inline RefPtr::~RefPtr() noexcept -{ - if (pCppObject_) - pCppObject_->unreference(); // This could cause pCppObject to be deleted. -} - -template -inline RefPtr::RefPtr(T_CppObject* pCppObject) noexcept : pCppObject_(pCppObject) -{ -} - -template -inline RefPtr::RefPtr(const RefPtr& src) noexcept : pCppObject_(src.pCppObject_) -{ - if (pCppObject_) - pCppObject_->reference(); -} - -template -inline RefPtr::RefPtr(RefPtr&& src) noexcept : pCppObject_(src.pCppObject_) -{ - src.pCppObject_ = nullptr; -} - -template -template -inline RefPtr::RefPtr(RefPtr&& 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 -template -inline RefPtr::RefPtr(const RefPtr& 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 -inline void -RefPtr::swap(RefPtr& other) noexcept -{ - T_CppObject* const temp = pCppObject_; - pCppObject_ = other.pCppObject_; - other.pCppObject_ = temp; -} - -template -inline RefPtr& -RefPtr::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 temp(src); - this->swap(temp); - return *this; -} - -template -inline RefPtr& -RefPtr::operator=(RefPtr&& src) noexcept -{ - RefPtr temp(std::move(src)); - this->swap(temp); - src.pCppObject_ = nullptr; - - return *this; -} - -template -template -inline RefPtr& -RefPtr::operator=(RefPtr&& src) noexcept -{ - if (pCppObject_) - pCppObject_->unreference(); - pCppObject_ = src.release(); - - return *this; -} - -template -template -inline RefPtr& -RefPtr::operator=(const RefPtr& src) noexcept -{ - RefPtr temp(src); - this->swap(temp); - return *this; -} - -template -inline bool -RefPtr::operator==(const RefPtr& src) const noexcept -{ - return (pCppObject_ == src.pCppObject_); -} - -template -inline bool -RefPtr::operator!=(const RefPtr& src) const noexcept -{ - return (pCppObject_ != src.pCppObject_); -} - -template -inline RefPtr::operator bool() const noexcept -{ - return (pCppObject_ != nullptr); -} - -template -inline void -RefPtr::reset() noexcept -{ - RefPtr temp; // swap with an empty RefPtr<> to clear *this - this->swap(temp); -} - -template -inline T_CppObject* -RefPtr::release() noexcept -{ - T_CppObject* tmp = pCppObject_; - pCppObject_ = nullptr; - return tmp; -} - -template -template -inline RefPtr -RefPtr::cast_dynamic(const RefPtr& src) noexcept -{ - T_CppObject* const pCppObject = dynamic_cast(src.operator->()); - - if (pCppObject) - pCppObject->reference(); - - return RefPtr(pCppObject); -} - -template -template -inline RefPtr -RefPtr::cast_static(const RefPtr& src) noexcept -{ - T_CppObject* const pCppObject = static_cast(src.operator->()); - - if (pCppObject) - pCppObject->reference(); - - return RefPtr(pCppObject); -} - -template -template -inline RefPtr -RefPtr::cast_const(const RefPtr& src) noexcept -{ - T_CppObject* const pCppObject = const_cast(src.operator->()); - - if (pCppObject) - pCppObject->reference(); - - return RefPtr(pCppObject); -} - -template -inline bool -RefPtr::operator<(const RefPtr& src) const noexcept -{ - return (pCppObject_ < src.pCppObject_); -} - -template -inline bool -RefPtr::operator<=(const RefPtr& src) const noexcept -{ - return (pCppObject_ <= src.pCppObject_); -} +using RefPtr = std::shared_ptr; -template -inline bool -RefPtr::operator>(const RefPtr& src) const noexcept -{ - return (pCppObject_ > src.pCppObject_); -} - -template -inline bool -RefPtr::operator>=(const RefPtr& src) const noexcept -{ - return (pCppObject_ >= src.pCppObject_); -} - -#endif /* DOXYGEN_SHOULD_SKIP_THIS */ - -/** @relates Glib::RefPtr */ -template -inline void -swap(RefPtr& lhs, RefPtr& 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 +RefPtr +make_refptr(T_Arg... arg) { - lhs.swap(rhs); + return RefPtr(new T_CppObject(arg...)); } +*/ template RefPtr make_refptr_for_instance(T_CppObject* object) { - return RefPtr(object); + return RefPtr(object, &RefPtrDeleter); } } // namespace Glib -- cgit v1.2.1