#pragma once #include #include namespace chatterino { /// Holds a pointer to a QObject and resets it to nullptr if the QObject /// gets destroyed. template class QObjectRef { public: QObjectRef() { static_assert(std::is_base_of_v); } explicit QObjectRef(T *t) { static_assert(std::is_base_of_v); this->set(t); } QObjectRef(const QObjectRef &other) { this->set(other.t_); } ~QObjectRef() { this->set(nullptr); } QObjectRef &operator=(T *t) { this->set(t); return *this; } operator bool() { return t_; } T *operator->() { return t_; } T *get() { return t_; } private: void set(T *other) { // old if (this->conn_) { QObject::disconnect(this->conn_); } // new if (other) { // the cast here should absolutely not be necessary, but gcc still requires it this->conn_ = QObject::connect((QObject *)other, &QObject::destroyed, qApp, [this](QObject *) { this->set(nullptr); }, Qt::DirectConnection); } this->t_ = other; } std::atomic t_{}; QMetaObject::Connection conn_; }; } // namespace chatterino