1 /* 2 * DQt - D bindings for the Qt Toolkit 3 * 4 * GNU Lesser General Public License Usage 5 * This file may be used under the terms of the GNU Lesser 6 * General Public License version 3 as published by the Free Software 7 * Foundation and appearing in the file LICENSE.LGPL3 included in the 8 * packaging of this file. Please review the following information to 9 * ensure the GNU Lesser General Public License version 3 requirements 10 * will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 11 */ 12 module qt.core.scopedpointer; 13 extern(C++): 14 15 import qt.config; 16 import qt.core.object; 17 import qt.helpers; 18 19 struct QScopedPointerDeleter(T) 20 { 21 static if(is(T == class)) 22 { 23 alias P = T; 24 enum IsIncompleteType = !__traits(compiles, __traits(classInstanceSize, T)); 25 } 26 else 27 { 28 alias P = T*; 29 enum IsIncompleteType = !__traits(compiles, T.sizeof); 30 } 31 static if(IsIncompleteType) 32 static void cleanup(P pointer); 33 else 34 pragma(inline, true) static void cleanup(P pointer) 35 { 36 import core.stdcpp.new_; 37 38 static if(IsIncompleteType) 39 assert(false); 40 else 41 cpp_delete(pointer); 42 } 43 } 44 45 /+ template <typename T> 46 struct QScopedPointerArrayDeleter 47 { 48 static inline void cleanup(T *pointer) noexcept 49 { 50 // Enforce a complete type. 51 // If you get a compile error here, read the section on forward declared 52 // classes in the QScopedPointer documentation. 53 typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; 54 (void) sizeof(IsIncompleteType); 55 56 delete[] pointer; 57 } 58 void operator()(T *pointer) const noexcept 59 { 60 cleanup(pointer); 61 } 62 }; 63 64 struct QScopedPointerPodDeleter 65 { 66 static inline void cleanup(void *pointer) noexcept { free(pointer); } 67 void operator()(void *pointer) const noexcept { cleanup(pointer); } 68 }; 69 70 #ifndef QT_NO_QOBJECT +/ 71 struct QScopedPointerObjectDeleteLater(T) if(is(T : QObject)) 72 { 73 pragma(inline, true) static void cleanup(T pointer) { if (pointer) pointer.deleteLater(); } 74 /+void operator ()(T* pointer) const { cleanup(pointer); }+/ 75 } 76 77 alias QScopedPointerDeleteLater = QScopedPointerObjectDeleteLater!(QObject); 78 /+ #endif +/ 79 80 /// Binding for C++ class [QScopedPointer](https://doc.qt.io/qt-6/qscopedpointer.html). 81 extern(C++, class) struct QScopedPointer(T, Cleanup = QScopedPointerDeleter!T) 82 { 83 private: 84 static if(is(T == class)) 85 { 86 alias P = T; 87 } 88 else 89 { 90 alias P = T*; 91 } 92 93 public: 94 /+ explicit +/this(P p/+ = null+/)/+ noexcept+/ 95 { 96 this.d = p; 97 } 98 99 pragma(inline, true) ~this() 100 { 101 assert(false); 102 /*P oldD = this.d; 103 Cleanup.cleanup(oldD);*/ 104 } 105 106 pragma(inline, true) ref T opUnary(string op)() const if(op == "*") 107 { 108 import qt.core.global; 109 110 (mixin(Q_ASSERT(q{d}))); 111 return *d; 112 } 113 114 /+P operator ->() const/+ noexcept+/ 115 { 116 return d; 117 }+/ 118 119 /+bool operator !() const/+ noexcept+/ 120 { 121 return !d; 122 }+/ 123 124 /+/+ explicit +/ auto opCast(T : bool)() const 125 { 126 return !isNull(); 127 }+/ 128 129 P data() const/+ noexcept+/ 130 { 131 return cast(P)d; 132 } 133 134 alias data this; 135 136 P get() const/+ noexcept+/ 137 { 138 return cast(P)d; 139 } 140 141 bool isNull() const/+ noexcept+/ 142 { 143 return !d; 144 } 145 146 /+ void reset(P other = null) /+ noexcept(noexcept(Cleanup::cleanup(std::declval<T *>()))) +/ 147 { 148 if (d == other) 149 return; 150 T* oldD = qExchange(d, cast(U && )(other)); 151 Cleanup.cleanup(oldD); 152 }+/ 153 154 /+ #if QT_DEPRECATED_SINCE(6, 1) +/ 155 /+ QT_DEPRECATED_VERSION_X_6_1("Use std::unique_ptr instead, and call release().") +/ 156 /+ T* take()/+ noexcept+/ 157 { 158 T* oldD = qExchange(d, cast(U && )(null)); 159 return oldD; 160 }+/ 161 /+ #endif 162 163 #if QT_DEPRECATED_SINCE(6, 2) +/ 164 /+ QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedPointer.") 165 void swap(QScopedPointer<T, Cleanup> &other) noexcept 166 { 167 qSwap(d, other.d); 168 } +/ 169 /+ #endif +/ 170 171 alias pointer = P; 172 173 /+ friend bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept 174 { 175 return lhs.data() == rhs.data(); 176 } +/ 177 178 /+ friend bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept 179 { 180 return lhs.data() != rhs.data(); 181 } +/ 182 183 /+ friend bool operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept 184 { 185 return lhs.isNull(); 186 } +/ 187 188 /+ friend bool operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept 189 { 190 return rhs.isNull(); 191 } +/ 192 193 /+ friend bool operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept 194 { 195 return !lhs.isNull(); 196 } +/ 197 198 /+ friend bool operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept 199 { 200 return !rhs.isNull(); 201 } +/ 202 203 /+ #if QT_DEPRECATED_SINCE(6, 2) +/ 204 /+ QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedPointer.") 205 friend void swap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) noexcept 206 { p1.swap(p2); } +/ 207 /+ #endif +/ 208 209 protected: 210 P d; 211 212 private: 213 /+ Q_DISABLE_COPY(QScopedPointer) +/ 214 @disable this(this); 215 /+this(ref const(QScopedPointer));+//+ref QScopedPointer operator =(ref const(QScopedPointer));+/} 216 217 /// Binding for C++ class [QScopedArrayPointer](https://doc.qt.io/qt-6/qscopedarraypointer.html). 218 class QScopedArrayPointer(T, Cleanup ) : QScopedPointer!(T, Cleanup) 219 { 220 private: 221 /+ template <typename Ptr> +/ 222 /+ using if_same_type = typename std::enable_if<std::is_same<typename std::remove_cv<T>::type, Ptr>::value, bool>::type; +/ 223 public: 224 pragma(inline, true) this() 225 { 226 this.QScopedPointer!(T, Cleanup) = null; 227 } 228 229 /+ template <typename D, if_same_type<D> = true> +/ 230 /+ explicit +/this(D,)(D* p) 231 { 232 this.QScopedPointer!(T, Cleanup) = p; 233 } 234 235 pragma(inline, true) final ref T opIndex(int i) 236 { 237 return this.d[i]; 238 } 239 240 pragma(inline, true) final ref const(T) opIndex(int i) const 241 { 242 return this.d[i]; 243 } 244 245 /+ #if QT_DEPRECATED_SINCE(6, 2) +/ 246 /+ QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedArrayPointer.") 247 void swap(QScopedArrayPointer &other) noexcept // prevent QScopedPointer <->QScopedArrayPointer swaps 248 { QScopedPointer<T, Cleanup>::swap(other); } +/ 249 /+ #endif +/ 250 251 private: 252 /+ explicit +/ pragma(inline, true) this(void* ) 253 { 254 // Enforce the same type. 255 256 // If you get a compile error here, make sure you declare 257 // QScopedArrayPointer with the same template type as you pass to the 258 // constructor. See also the QScopedPointer documentation. 259 260 // Storing a scalar array as a pointer to a different type is not 261 // allowed and results in undefined behavior. 262 } 263 264 /+ Q_DISABLE_COPY(QScopedArrayPointer) +/ 265 } 266 267 /+ #if QT_DEPRECATED_SINCE(6, 2) 268 template <typename T, typename Cleanup> 269 QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedArrayPointer.") 270 inline void swap(QScopedArrayPointer<T, Cleanup> &lhs, QScopedArrayPointer<T, Cleanup> &rhs) noexcept 271 { lhs.swap(rhs); } 272 #endif +/ 273