Files
tdesktop/Telegram/lib_base/base/object_ptr.h
allhaileris afb81b8278
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Close stale issues and PRs / stale (push) Successful in 13s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
init
2026-02-16 15:50:16 +03:00

125 lines
3.0 KiB
C++

// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#pragma once
#include <QtCore/QPointer>
// Smart pointer for QObject*, has move semantics, destroys object if it doesn't have a parent.
template <typename Object>
class object_ptr {
public:
object_ptr(std::nullptr_t) noexcept {
}
// No default constructor, but constructors with at least
// one argument are simply make functions.
template <typename Parent, typename... Args>
explicit object_ptr(Parent &&parent, Args&&... args)
: _object(new Object(std::forward<Parent>(parent), std::forward<Args>(args)...)) {
}
static object_ptr<Object> fromRaw(Object *value) noexcept {
object_ptr<Object> result = { nullptr };
result._object = value;
return result;
}
Object *release() noexcept {
return static_cast<Object*>(base::take(_object).data());
}
object_ptr(const object_ptr &other) = delete;
object_ptr &operator=(const object_ptr &other) = delete;
object_ptr(object_ptr &&other) noexcept : _object(base::take(other._object)) {
}
object_ptr &operator=(object_ptr &&other) noexcept {
auto temp = std::move(other);
destroy();
std::swap(_object, temp._object);
return *this;
}
template <
typename OtherObject,
typename = std::enable_if_t<
std::is_base_of_v<Object, OtherObject>>>
object_ptr(object_ptr<OtherObject> &&other) noexcept
: _object(base::take(other._object)) {
}
template <
typename OtherObject,
typename = std::enable_if_t<
std::is_base_of_v<Object, OtherObject>>>
object_ptr &operator=(object_ptr<OtherObject> &&other) noexcept {
_object = base::take(other._object);
return *this;
}
object_ptr &operator=(std::nullptr_t) noexcept {
_object = nullptr;
return *this;
}
Object *get() const noexcept {
return static_cast<Object*>(_object.data());
}
// So we can pass this pointer to methods like connect().
Object *data() const noexcept {
return get();
}
operator Object*() const noexcept {
return get();
}
explicit operator bool() const noexcept {
return _object.data() != nullptr;
}
Object *operator->() const noexcept {
return get();
}
Object &operator*() const noexcept {
return *get();
}
// Use that instead "= new Object(parent, ...)"
template <typename Parent, typename... Args>
Object *create(Parent &&parent, Args&&... args) {
destroy();
_object = new Object(
std::forward<Parent>(parent),
std::forward<Args>(args)...);
return get();
}
void destroy() noexcept {
delete base::take(_object);
}
void destroyDelayed() {
if (_object) {
if (auto widget = base::up_cast<QWidget*>(get())) {
widget->hide();
}
base::take(_object)->deleteLater();
}
}
~object_ptr() noexcept {
if (auto pointer = _object) {
if (!pointer->parent()) {
destroy();
}
}
}
private:
template <typename OtherObject>
friend class object_ptr;
QPointer<QObject> _object;
};