/** ** ** @RDE_HEADER@ ** Base class for reference counted objects ** $Id$ ** $HeadURL$ ** $Author$ ** ** ----------------------------------------------------------------------------------------------- ** ** Hardware-Umgebung: Intel-PC ** Software-Umgebung: Linux, Windows 7, Qt 5.4. ArcGIS 10.2.5 ** ** Pgrm-Sprache ....: C++ 11 ** ** HIER/SACHN ......: P: -- ---- - --- QE ** ** Version .........: $Revision$ ** ----------------------------------------------------------------------------------------------- ** ** Autor ...........: Nikolaus Hanekamp, SEDG, Tel. 2906 ** ** ----------------------------------------------------------------------------------------------- ** ** Notizen .........: ** ** 18.08.2004, NH : Urversion ** 13.05.2015, JT : Refactoring for use with Qt5, ArcGIS 10.2.5 ** adding methodes according to std::share_ptr like reset ** ** ----------------------------------------------------------------------------------------------- ** ** Copyright (C) 2004 Rheinmetall Defence Electronics GmbH, D-28309 BREMEN ** ** ----------------------------------------------------------------------------------------------- */ #pragma once #include "referenced.h" namespace SituationMap { /** @class RefPointer ref_pointer.h @brief Smart pointer for handling referenced counted objects Simple class template to implement reference counted pointers or smart pointers. The RefPointer class controls the reference counter of the object \c T the pointer points to. The class \c T have to be derived from class \c Referenced, where the reference counter member variable is located. In case of this reference counter gets zero delete will be called automatically. @see Referenced */ template class RefPointer { public: using ElementType = T; /** @name Construction and Destruction @{ */ RefPointer() : RefPointer(nullptr) {} RefPointer(const RefPointer &rp) : RefPointer(rp._ptr) {} explicit RefPointer(ElementType *t) : _ptr(t) { static_assert(std::is_base_of::value , "Class of template SituationMap::RefPointer have to be derived from class SituationMap::Referenced"); if (_ptr) _ptr->ref(); } /* RefPointer */ ~RefPointer() { if (_ptr) _ptr->unref(); _ptr = nullptr; } /* ~RefPointer */ /** @} */ /** Checks if pointer is valid. */ explicit inline operator bool() const { return (_ptr != nullptr); } /** @name Casting @{ */ /** To create reference pointer from a derived class directly this contructor template can be used. How to use it is shown in the following example: \code RefPointer objPtr = getAbstractMapObject(); RefPointer participantObj( objPtr ); if (participantObj != NULL) { ... } \endcode Alternatively it is posible to create \b participantObj from example above as follows: \code RefPointer participantObj = RefPointer(dynamic_cast(objPtr.get())); \endcode */ template explicit RefPointer(RefPointer assignPtr) { _ptr = dynamic_cast(assignPtr.get()); if (_ptr) _ptr->ref(); } template explicit RefPointer(Y *assignPtr) { _ptr = dynamic_cast(assignPtr); if (_ptr) _ptr->ref(); } /** @} */ inline RefPointer &operator = (const RefPointer &rp) { if (_ptr == rp._ptr) return *this; T *tmp_ptr = _ptr; _ptr = rp._ptr; if (_ptr) _ptr->ref(); // unref second to prevent any deletion of any object which might // be referenced by the other object. i.e rp is child of the // original _ptr. if (tmp_ptr) tmp_ptr->unref(); return *this; } inline RefPointer &operator = (ElementType *ptr) { if (_ptr == ptr) return *this; T *tmp_ptr = _ptr; _ptr = ptr; if (_ptr) _ptr->ref(); // unref second to prevent any deletion of any object which might // be referenced by the other object. i.e rp is child of the // original _ptr. if (tmp_ptr) tmp_ptr->unref(); return *this; } inline void reset() { *this = nullptr; } inline void reset(T *ptr) { *this = ptr; } /** @name Comparison Operators Compares the pointer element \c _ptr with other pointers. @{ */ inline bool operator == (const RefPointer &rp) const { return (_ptr == rp._ptr); } inline bool operator != (const RefPointer &rp) const { return (_ptr != rp._ptr); } inline bool operator < (const RefPointer &rp) const { return (_ptr < rp._ptr); } inline bool operator > (const RefPointer &rp) const { return (_ptr > rp._ptr); } inline bool operator == (const ElementType *ptr) const { return (_ptr == ptr); } inline bool operator != (const ElementType *ptr) const { return (_ptr != ptr); } inline bool operator < (const ElementType *ptr) const { return (_ptr < ptr); } inline bool operator > (const ElementType *ptr) const { return (_ptr > ptr); } /** @} */ /** @name Access Operators Get access to the pointer or the object it points to. @{ */ inline ElementType &operator*() { return *_ptr; } inline const ElementType &operator*() const { return *_ptr; } inline ElementType *operator->() { return _ptr; } inline const ElementType *operator->() const { return _ptr; } inline ElementType *get() { return _ptr; } inline const ElementType *get() const { return _ptr; } /** @} */ /** @name Checks if the pointer is valid. @{ */ inline bool valid() const { return _ptr != nullptr; } inline bool operator!() const { return _ptr == nullptr; } /** @} */ /** * @name Control Over Object Pointer * Take control over the object pointed to by RefPointer, unreference but do not delete even if ref count goes to 0, * return the pointer to the object. * Note, do not use this unless you are 100% sure your code handles the deletion of the object correctly, and * only use when absolutely required. @{ */ inline ElementType *take() { return release();} inline ElementType *release() { T *tmp = _ptr; if (_ptr) _ptr->unref_nodelete(); _ptr = nullptr; return tmp;} /** @} */ private: ElementType *_ptr; }; } // SituationMap