object_ptr.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #pragma once
  8. #include <QtCore/QPointer>
  9. // Smart pointer for QObject*, has move semantics, destroys object if it doesn't have a parent.
  10. template <typename Object>
  11. class object_ptr {
  12. public:
  13. object_ptr(std::nullptr_t) noexcept {
  14. }
  15. // No default constructor, but constructors with at least
  16. // one argument are simply make functions.
  17. template <typename Parent, typename... Args>
  18. explicit object_ptr(Parent &&parent, Args&&... args)
  19. : _object(new Object(std::forward<Parent>(parent), std::forward<Args>(args)...)) {
  20. }
  21. static object_ptr<Object> fromRaw(Object *value) noexcept {
  22. object_ptr<Object> result = { nullptr };
  23. result._object = value;
  24. return result;
  25. }
  26. Object *release() noexcept {
  27. return static_cast<Object*>(base::take(_object).data());
  28. }
  29. object_ptr(const object_ptr &other) = delete;
  30. object_ptr &operator=(const object_ptr &other) = delete;
  31. object_ptr(object_ptr &&other) noexcept : _object(base::take(other._object)) {
  32. }
  33. object_ptr &operator=(object_ptr &&other) noexcept {
  34. auto temp = std::move(other);
  35. destroy();
  36. std::swap(_object, temp._object);
  37. return *this;
  38. }
  39. template <
  40. typename OtherObject,
  41. typename = std::enable_if_t<
  42. std::is_base_of_v<Object, OtherObject>>>
  43. object_ptr(object_ptr<OtherObject> &&other) noexcept
  44. : _object(base::take(other._object)) {
  45. }
  46. template <
  47. typename OtherObject,
  48. typename = std::enable_if_t<
  49. std::is_base_of_v<Object, OtherObject>>>
  50. object_ptr &operator=(object_ptr<OtherObject> &&other) noexcept {
  51. _object = base::take(other._object);
  52. return *this;
  53. }
  54. object_ptr &operator=(std::nullptr_t) noexcept {
  55. _object = nullptr;
  56. return *this;
  57. }
  58. // So we can pass this pointer to methods like connect().
  59. Object *data() const noexcept {
  60. return static_cast<Object*>(_object.data());
  61. }
  62. operator Object*() const noexcept {
  63. return data();
  64. }
  65. explicit operator bool() const noexcept {
  66. return _object != nullptr;
  67. }
  68. Object *operator->() const noexcept {
  69. return data();
  70. }
  71. Object &operator*() const noexcept {
  72. return *data();
  73. }
  74. // Use that instead "= new Object(parent, ...)"
  75. template <typename Parent, typename... Args>
  76. Object *create(Parent &&parent, Args&&... args) {
  77. destroy();
  78. _object = new Object(
  79. std::forward<Parent>(parent),
  80. std::forward<Args>(args)...);
  81. return data();
  82. }
  83. void destroy() noexcept {
  84. delete base::take(_object);
  85. }
  86. void destroyDelayed() {
  87. if (_object) {
  88. if (auto widget = base::up_cast<QWidget*>(data())) {
  89. widget->hide();
  90. }
  91. base::take(_object)->deleteLater();
  92. }
  93. }
  94. ~object_ptr() noexcept {
  95. if (auto pointer = _object) {
  96. if (!pointer->parent()) {
  97. destroy();
  98. }
  99. }
  100. }
  101. private:
  102. template <typename OtherObject>
  103. friend class object_ptr;
  104. QPointer<QObject> _object;
  105. };