unique_qptr.h 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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 "base/algorithm.h"
  9. #include <QtCore/QPointer>
  10. #include <QtCore/QObject>
  11. namespace base {
  12. template <typename T>
  13. class unique_qptr {
  14. public:
  15. unique_qptr() = default;
  16. unique_qptr(std::nullptr_t) noexcept {
  17. }
  18. explicit unique_qptr(T *pointer) noexcept
  19. : _object(pointer) {
  20. }
  21. unique_qptr(const unique_qptr &other) = delete;
  22. unique_qptr &operator=(const unique_qptr &other) = delete;
  23. unique_qptr(unique_qptr &&other) noexcept
  24. : _object(base::take(other._object)) {
  25. }
  26. unique_qptr &operator=(unique_qptr &&other) noexcept {
  27. if (_object != other._object) {
  28. destroy();
  29. _object = base::take(other._object);
  30. }
  31. return *this;
  32. }
  33. template <
  34. typename U,
  35. typename = std::enable_if_t<std::is_base_of_v<T, U>>>
  36. unique_qptr(unique_qptr<U> &&other) noexcept
  37. : _object(base::take(other._object)) {
  38. }
  39. template <
  40. typename U,
  41. typename = std::enable_if_t<std::is_base_of_v<T, U>>>
  42. unique_qptr &operator=(unique_qptr<U> &&other) noexcept {
  43. if (_object != other._object) {
  44. destroy();
  45. _object = base::take(other._object);
  46. }
  47. return *this;
  48. }
  49. unique_qptr &operator=(std::nullptr_t) noexcept {
  50. destroy();
  51. return *this;
  52. }
  53. template <typename ...Args>
  54. explicit unique_qptr(std::in_place_t, Args &&...args)
  55. : _object(new T(std::forward<Args>(args)...)) {
  56. }
  57. template <typename ...Args>
  58. T *emplace(Args &&...args) {
  59. reset(new T(std::forward<Args>(args)...));
  60. return get();
  61. }
  62. void reset(T *value = nullptr) noexcept {
  63. if (_object != value) {
  64. destroy();
  65. _object = value;
  66. }
  67. }
  68. T *get() const noexcept {
  69. return static_cast<T*>(_object.data());
  70. }
  71. operator T*() const noexcept {
  72. return get();
  73. }
  74. T *release() noexcept {
  75. return static_cast<T*>(base::take(_object).data());
  76. }
  77. explicit operator bool() const noexcept {
  78. return _object != nullptr;
  79. }
  80. T *operator->() const noexcept {
  81. return get();
  82. }
  83. T &operator*() const noexcept {
  84. return *get();
  85. }
  86. ~unique_qptr() noexcept {
  87. destroy();
  88. }
  89. private:
  90. void destroy() noexcept {
  91. delete base::take(_object).data();
  92. }
  93. template <typename U>
  94. friend class unique_qptr;
  95. QPointer<QObject> _object;
  96. };
  97. template <typename T, typename ...Args>
  98. inline unique_qptr<T> make_unique_q(Args &&...args) {
  99. return unique_qptr<T>(std::in_place, std::forward<Args>(args)...);
  100. }
  101. } // namespace base