From 5df61f19dc6486e2282fc7e61c46e4dc3e92549d Mon Sep 17 00:00:00 2001 From: Timothy Rae Date: Mon, 23 Jan 2017 17:46:37 +0900 Subject: [PATCH] Introduce parented_ptr class which is owned by the QT object tree --- src/util/parented_ptr.h | 88 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/util/parented_ptr.h diff --git a/src/util/parented_ptr.h b/src/util/parented_ptr.h new file mode 100644 index 000000000000..7151570fc2c8 --- /dev/null +++ b/src/util/parented_ptr.h @@ -0,0 +1,88 @@ +#ifndef UTIL_PARENTED_POINTER_H +#define UTIL_PARENTED_POINTER_H + +#include +#include "util/assert.h" + + +/** + * Use this wrapper class to clearly represent a pointer that is owned by the QT object tree. + * Objects which both derive from QObject AND have a parent object, have their lifetime governed by the QT object tree, + * and thus pointers to such objects do not need to be deleted when they go out of scope. +**/ +template +class parented_ptr { + public: + explicit parented_ptr(T* t) : m_pObject(t) { + DEBUG_ASSERT(t->parent() != nullptr); + } + + /* If U* is convertible to T* then we also want parented_ptr convertible to parented_ptr */ + template + parented_ptr(const parented_ptr& u, typename std::enable_if::value, void>::type * = 0) + : m_pObject(u.get()) { + DEBUG_ASSERT(u->parent() != nullptr); + } + + parented_ptr() : m_pObject(nullptr) {} + + ~parented_ptr() = default; + + T* get() const { + return m_pObject; + } + + T& operator* () const { + return *m_pObject; + } + + T* operator-> () const { + return m_pObject; + } + + bool operator== (const parented_ptr& other) const { + return m_pObject == other.m_ptr; + } + + bool operator== (const T* other) const { + return m_pObject == other; + } + + bool operator!= (const parented_ptr& other) const { + return m_pObject != other.m_pObject; + } + + bool operator!= (const T* other) const { + return m_pObject != other; + } + + operator bool() const { + return m_pObject != nullptr; + } + + /* + * If U* is convertible to T* then we also want parented_ptr assignable to parented_ptr + * E.g. parented_ptr base = make_parented(); should work as expected. + */ + template + typename std::enable_if::value, parented_ptr&>::type + operator=(const parented_ptr& p) { + m_pObject = p.get(); + return *this; + } + + private: + T* m_pObject; +}; + +namespace { + +template +inline parented_ptr make_parented(Args&&... args) { + return parented_ptr(new T(std::forward(args)...)); +} + + +} // namespace + +#endif /* UTIL_PARENTED_POINTER_H */