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.variant;
13 extern(C++):
14 
15 import qt.config;
16 import qt.core.abstractitemmodel;
17 import qt.core.atomic;
18 import qt.core.bitarray;
19 import qt.core.bytearray;
20 import qt.core.compare;
21 import qt.core.datetime;
22 import qt.core.easingcurve;
23 import qt.core.global;
24 import qt.core.hash;
25 import qt.core.list;
26 import qt.core.locale;
27 import qt.core.map;
28 import qt.core.metatype;
29 import qt.core.namespace;
30 import qt.core.qchar;
31 import qt.core.regularexpression;
32 import qt.core.string;
33 import qt.core.stringlist;
34 import qt.core.typeinfo;
35 import qt.core.url;
36 import qt.core.uuid;
37 import qt.helpers;
38 version(QT_NO_DATASTREAM){}else
39     import qt.core.datastream;
40 version(QT_NO_GEOM_VARIANT){}else
41 {
42     import qt.core.line;
43     import qt.core.point;
44     import qt.core.rect;
45     import qt.core.size;
46 }
47 
48 /+ #ifndef QT_NO_DEBUG_STREAM
49 #endif
50 #ifndef QT_BOOTSTRAPPED
51 #endif
52 #if __has_include(<variant>) && __cplusplus >= 201703L
53 #elif defined(Q_CLANG_QDOC)
54 namespace std { template<typename...> struct variant; }
55 #endif
56 
57 
58 
59 #if QT_CONFIG(easingcurve)
60 class QEasingCurve;
61 #endif
62 #if QT_CONFIG(regularexpression)
63 class QRegularExpression;
64 #endif +/ // QT_CONFIG(regularexpression)
65 
66 /// Binding for C++ class [QVariant](https://doc.qt.io/qt-6/qvariant.html).
67 @Q_RELOCATABLE_TYPE extern(C++, class) struct /+ Q_CORE_EXPORT +/ QVariant
68 {
69  public:
70 /+ #if QT_DEPRECATED_SINCE(6, 0) +/
71     enum /+ QT_DEPRECATED_VERSION_X_6_0("Use QMetaType::Type instead.") +/ Type
72     {
73         Invalid = QMetaType.Type.UnknownType,
74         Bool = QMetaType.Type.Bool,
75         Int = QMetaType.Type.Int,
76         UInt = QMetaType.Type.UInt,
77         LongLong = QMetaType.Type.LongLong,
78         ULongLong = QMetaType.Type.ULongLong,
79         Double = QMetaType.Type.Double,
80         Char = QMetaType.Type.QChar,
81         Map = QMetaType.Type.QVariantMap,
82         List = QMetaType.Type.QVariantList,
83         String = QMetaType.Type.QString,
84         StringList = QMetaType.Type.QStringList,
85         ByteArray = QMetaType.Type.QByteArray,
86         BitArray = QMetaType.Type.QBitArray,
87         Date = QMetaType.Type.QDate,
88         Time = QMetaType.Type.QTime,
89         DateTime = QMetaType.Type.QDateTime,
90         Url = QMetaType.Type.QUrl,
91         Locale = QMetaType.Type.QLocale,
92         Rect = QMetaType.Type.QRect,
93         RectF = QMetaType.Type.QRectF,
94         Size = QMetaType.Type.QSize,
95         SizeF = QMetaType.Type.QSizeF,
96         Line = QMetaType.Type.QLine,
97         LineF = QMetaType.Type.QLineF,
98         Point = QMetaType.Type.QPoint,
99         PointF = QMetaType.Type.QPointF,
100 /+ #if QT_CONFIG(regularexpression) +/
101         RegularExpression = QMetaType.Type.QRegularExpression,
102 /+ #endif +/
103         Hash = QMetaType.Type.QVariantHash,
104 /+ #if QT_CONFIG(easingcurve) +/
105         EasingCurve = QMetaType.Type.QEasingCurve,
106 /+ #endif +/
107         Uuid = QMetaType.Type.QUuid,
108 /+ #if QT_CONFIG(itemmodel) +/
109         ModelIndex = QMetaType.Type.QModelIndex,
110         PersistentModelIndex = QMetaType.Type.QPersistentModelIndex,
111 /+ #endif +/
112         LastCoreType = QMetaType.Type.LastCoreType,
113 
114         Font = QMetaType.Type.QFont,
115         Pixmap = QMetaType.Type.QPixmap,
116         Brush = QMetaType.Type.QBrush,
117         Color = QMetaType.Type.QColor,
118         Palette = QMetaType.Type.QPalette,
119         Image = QMetaType.Type.QImage,
120         Polygon = QMetaType.Type.QPolygon,
121         Region = QMetaType.Type.QRegion,
122         Bitmap = QMetaType.Type.QBitmap,
123         Cursor = QMetaType.Type.QCursor,
124 /+ #if QT_CONFIG(shortcut) +/
125         KeySequence = QMetaType.Type.QKeySequence,
126 /+ #endif +/
127         Pen = QMetaType.Type.QPen,
128         TextLength = QMetaType.Type.QTextLength,
129         TextFormat = QMetaType.Type.QTextFormat,
130         Transform = QMetaType.Type.QTransform,
131         Matrix4x4 = QMetaType.Type.QMatrix4x4,
132         Vector2D = QMetaType.Type.QVector2D,
133         Vector3D = QMetaType.Type.QVector3D,
134         Vector4D = QMetaType.Type.QVector4D,
135         Quaternion = QMetaType.Type.QQuaternion,
136         PolygonF = QMetaType.Type.QPolygonF,
137         Icon = QMetaType.Type.QIcon,
138         LastGuiType = QMetaType.Type.LastGuiType,
139 
140         SizePolicy = QMetaType.Type.QSizePolicy,
141 
142         UserType = QMetaType.Type.User,
143 //        LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type
144     }
145 /+ #endif +/
146     /+this()/+ noexcept+/
147     {
148         this.d = typeof(this.d)();
149     }+/
150     ~this();
151     /+ explicit +/this(QMetaType type, const(void)* copy = null);
152     @disable this(this);
153     this(ref const(QVariant) other);
154 
155     this(int i);
156     this(uint ui);
157     this(qlonglong ll);
158     this(qulonglong ull);
159     this(bool b);
160     this(double d);
161     this(float f);
162 /+ #ifndef QT_NO_CAST_FROM_ASCII
163     QT_ASCII_CAST_WARN QVariant(const char *str)
164         : QVariant(QString::fromUtf8(str))
165     {}
166 #endif +/
167 
168     this(ref const(QByteArray) bytearray);
169     this(ref const(QBitArray) bitarray);
170     this(ref const(QString) string);
171     this(QLatin1String string);
172     this(ref const(QStringList) stringlist);
173     this(QChar qchar);
174     this(QDate date);
175     this(QTime time);
176     this(ref const(QDateTime) datetime);
177     this(ref const(QList!(QVariant)) list);
178 //    this(ref const(QMap!(QString, QVariant)) map);
179 //    this(ref const(QHash!(QString, QVariant)) hash);
180     version(QT_NO_GEOM_VARIANT){}else
181     {
182         this(ref const(QSize) size);
183         this(ref const(QSizeF) size);
184         this(ref const(QPoint) pt);
185         this(ref const(QPointF) pt);
186         this(ref const(QLine) line);
187         this(ref const(QLineF) line);
188         this(ref const(QRect) rect);
189         this(ref const(QRectF) rect);
190     }
191     this(ref const(QLocale) locale);
192 /+ #if QT_CONFIG(regularexpression) +/
193     this(ref const(QRegularExpression) re);
194 /+ #endif // QT_CONFIG(regularexpression)
195 #if QT_CONFIG(easingcurve) +/
196     this(ref const(QEasingCurve) easing);
197 /+ #endif +/
198     this(ref const(QUuid) uuid);
199 /+ #ifndef QT_BOOTSTRAPPED +/
200     this(ref const(QUrl) url);
201 //    this(ref const(QJsonValue) jsonValue);
202 //    this(ref const(QJsonObject) jsonObject);
203 //    this(ref const(QJsonArray) jsonArray);
204 //    this(ref const(QJsonDocument) jsonDocument);
205 /+ #endif // QT_BOOTSTRAPPED
206 #if QT_CONFIG(itemmodel) +/
207     this(ref const(QModelIndex) modelIndex);
208     this(ref const(QPersistentModelIndex) modelIndex);
209 /+ #endif +/
210 
211     /+ref QVariant operator =(ref const(QVariant) other);+/
212     /+ inline QVariant(QVariant &&other) noexcept : d(other.d)
213     { other.d = Private(); } +/
214     /+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QVariant) +/
215 
216     /+ inline void swap(QVariant &other) noexcept { qSwap(d, other.d); } +/
217 
218     int userType() const { return typeId(); }
219     int typeId() const { return metaType().id(); }
220 
221     const(char)* typeName() const;
222     QMetaType metaType() const;
223 
224     bool canConvert(QMetaType targetType) const
225     { return QMetaType.canConvert(d.type(), targetType); }
226     bool convert(QMetaType type);
227 
228     bool canView(QMetaType targetType) const
229     { return QMetaType.canView(d.type(), targetType); }
230 
231 /+ #if QT_DEPRECATED_SINCE(6, 0) +/
232     /+ QT_DEPRECATED_VERSION_6_0 +/
233         bool canConvert(int targetTypeId) const
234     { return QMetaType.canConvert(d.type(), QMetaType(targetTypeId)); }
235     /+ QT_DEPRECATED_VERSION_6_0 +/
236         bool convert(int targetTypeId)
237     { return convert(QMetaType(targetTypeId)); }
238 /+ #endif +/
239 
240     pragma(inline, true) bool isValid() const
241     {
242         return d.type().isValid();
243     }
244     bool isNull() const;
245 
246     void clear();
247 
248     void detach();
249     pragma(inline, true) bool isDetached() const
250     { return !d.is_shared || d.data.shared_.ref_.loadRelaxed() == 1; }
251 
252     int toInt(bool* ok = null) const;
253     uint toUInt(bool* ok = null) const;
254     qlonglong toLongLong(bool* ok = null) const;
255     qulonglong toULongLong(bool* ok = null) const;
256     bool toBool() const;
257     double toDouble(bool* ok = null) const;
258     float toFloat(bool* ok = null) const;
259     qreal toReal(bool* ok = null) const;
260     QByteArray toByteArray() const;
261     QBitArray toBitArray() const;
262     QString toString() const;
263     QStringList toStringList() const;
264     QChar toChar() const;
265     QDate toDate() const;
266     QTime toTime() const;
267     QDateTime toDateTime() const;
268     QList!(QVariant) toList() const;
269 //    QMap!(QString, QVariant) toMap() const;
270 //    QHash!(QString, QVariant) toHash() const;
271 
272     version(QT_NO_GEOM_VARIANT){}else
273     {
274         QPoint toPoint() const;
275         QPointF toPointF() const;
276         QRect toRect() const;
277         QSize toSize() const;
278         QSizeF toSizeF() const;
279         QLine toLine() const;
280         QLineF toLineF() const;
281         QRectF toRectF() const;
282     }
283     QLocale toLocale() const;
284 /+ #if QT_CONFIG(regularexpression) +/
285     QRegularExpression toRegularExpression() const;
286 /+ #endif // QT_CONFIG(regularexpression)
287 #if QT_CONFIG(easingcurve) +/
288     QEasingCurve toEasingCurve() const;
289 /+ #endif +/
290     QUuid toUuid() const;
291 /+ #ifndef QT_BOOTSTRAPPED +/
292     QUrl toUrl() const;
293     /+ QJsonValue toJsonValue() const; +/
294     /+ QJsonObject toJsonObject() const; +/
295     /+ QJsonArray toJsonArray() const; +/
296     /+ QJsonDocument toJsonDocument() const; +/
297 /+ #endif // QT_BOOTSTRAPPED
298 #if QT_CONFIG(itemmodel) +/
299     QModelIndex toModelIndex() const;
300     QPersistentModelIndex toPersistentModelIndex() const;
301 /+ #endif
302 
303 #ifndef QT_NO_DATASTREAM +/
304     version(QT_NO_DATASTREAM){}else
305     {
306         void load(ref QDataStream ds);
307         void save(ref QDataStream ds) const;
308     }
309 /+ #endif
310 #if QT_DEPRECATED_SINCE(6, 0)
311     QT_WARNING_PUSH
312     QT_WARNING_DISABLE_DEPRECATED +/
313     /+ QT_DEPRECATED_VERSION_X_6_0("Use the constructor taking a QMetaType instead.") +/
314         /+ explicit +/this(Type type)
315         {
316             this(QMetaType(int(type)));
317         }
318     /+ QT_DEPRECATED_VERSION_X_6_0("Use typeId() or metaType().") +/
319         Type type() const
320     {
321         int type = d.typeId();
322         return type >= QMetaType.Type.User ? Type.UserType : static_cast!(Type)(type);
323     }
324     /+ QT_DEPRECATED_VERSION_6_0 +/
325         static const(char)* typeToName(int typeId)
326     { return QMetaType(typeId).name(); }
327     /+ QT_DEPRECATED_VERSION_6_0 +/
328         static Type nameToType(const(char)* name)
329     {
330         import qt.core.bytearrayview;
331 
332         int metaType = QMetaType.fromName(cast(QByteArrayView)(name)).id();
333         return metaType <= int(Type.UserType) ? cast(QVariant.Type)(metaType) : Type.UserType;
334     }
335     /+ QT_WARNING_POP
336 #endif +/
337 
338     void* data();
339     const(void)* constData() const
340     { return d.storage(); }
341     pragma(inline, true) const(void)* data() const { return constData(); }
342 
343     /+ template<typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, QVariant>>> +/
344     /+ void setValue(T &&avalue)
345     {
346         using VT = std::decay_t<T>;
347         QMetaType metaType = QMetaType::fromType<VT>();
348         // If possible we reuse the current QVariant private.
349         if (isDetached() && d.type() == metaType) {
350             *reinterpret_cast<VT *>(const_cast<void *>(constData())) = std::forward<T>(avalue);
351         } else {
352             *this = QVariant::fromValue<VT>(std::forward<T>(avalue));
353         }
354     } +/
355 
356     void setValue(ref const(QVariant) avalue)
357     {
358         this = avalue;
359     }
360 
361     /+ void setValue(QVariant &&avalue)
362     {
363         *this = std::move(avalue);
364     } +/
365 
366     pragma(inline, true) T value(T)() const
367     { return qvariant_cast!(T)(this); }
368 
369     /+ template<typename T> +/
370     /+ pragma(inline, true) T view(T)()
371     {
372         T t T();
373         QMetaType.view(metaType(), data(), QMetaType.fromType!(T)(), &t);
374         return t;
375     } +/
376 
377     /+ template<typename T>
378 #ifndef Q_CLANG_QDOC +/
379     pragma(inline, true) static QVariant fromValue(T)(ref const T value)/+ ->
380         std::enable_if_t<std::is_copy_constructible_v<T>, QVariant> +/
381 /+ #else
382     static inline QVariant fromValue(const T &value)
383 #endif +/
384     {
385         return QVariant(QMetaType.fromType!(T)(), &value);
386     }
387 
388 /+ #if (__has_include(<variant>) && __cplusplus >= 201703L) || defined(Q_CLANG_QDOC) +/
389     /+ template<typename... Types> +/
390     /+ static inline QVariant fromStdVariant(const std::variant<Types...> &value)
391     {
392         if (value.valueless_by_exception())
393             return QVariant();
394         return std::visit([](const auto &arg) { return fromValue(arg); }, value);
395     } +/
396 /+ #endif +/
397 
398     /+ template<typename T> +/
399     bool canConvert(T)() const
400     { return canConvert(QMetaType.fromType!(T)()); }
401 
402     /+ template<typename T> +/
403     bool canView(T)() const
404     { return canView(QMetaType.fromType!(T)()); }
405 
406 public:
407     struct PrivateShared
408     {
409     private:
410         @disable this();
411         /+pragma(inline, true) this()
412         {
413             this.ref_ = 1;
414         }+/
415     public:
416         /+ static PrivateShared *create(const QtPrivate::QMetaTypeInterface *type)
417         {
418             Q_ASSERT(type);
419             size_t size = type->size;
420             size_t align = type->alignment;
421 
422             size += sizeof(PrivateShared);
423             if (align > sizeof(PrivateShared)) {
424                 // The alignment is larger than the alignment we can guarantee for the pointer
425                 // directly following PrivateShared, so we need to allocate some additional
426                 // memory to be able to fit the object into the available memory with suitable
427                 // alignment.
428                 size += align - sizeof(PrivateShared);
429             }
430             void *data = operator new(size);
431             auto *ps = new (data) QVariant::PrivateShared();
432             ps->offset = int(((quintptr(ps) + sizeof(PrivateShared) + align - 1) & ~(align - 1)) - quintptr(ps));
433             return ps;
434         } +/
435         static void free(PrivateShared* p)
436         {
437             destroy!false(p);
438 //            operator delete(p);
439         }
440 
441         /+ alignas(8) +/ QAtomicInt ref_ = QAtomicInt(1);
442         int offset;
443 
444         const(void)* data() const
445         { return reinterpret_cast!(const(ubyte)*)(&this) + offset; }
446         void* data()
447         { return reinterpret_cast!(ubyte*)(&this) + offset; }
448     }
449     struct Private
450     {
451         extern(D) static immutable size_t MaxInternalSize = 3*(void*).sizeof;
452         /+ template<typename T> +/
453         /+ static constexpr bool CanUseInternalSpace = (QTypeInfo<T>::isRelocatable && sizeof(T) <= MaxInternalSize && alignof(T) <= alignof(double)); +/
454         static bool canUseInternalSpace(/+ QtPrivate:: +/qt.core.metatype.QMetaTypeInterface* type)
455         {
456             import qt.core.flags;
457 
458             (mixin(Q_ASSERT(q{type})));
459             return QMetaType.TypeFlags(cast(QFlag)(type.flags)) & QMetaType.TypeFlag.RelocatableType &&
460                    size_t(type.size) <= MaxInternalSize && size_t(type.alignment) <= double.alignof;
461         }
462 
463         union generated_qvariant_0
464         {
465             uchar[MaxInternalSize] data = [0];
466             PrivateShared* shared_;
467             double _forAlignment; // we want an 8byte alignment on 32bit systems as well
468         }generated_qvariant_0 data;
469         quintptr bitfield = 1 << 1;
470         /+ quintptr is_shared : 1; +/
471         final quintptr is_shared() const
472         {
473             return (bitfield >> 0) & 0x1;
474         }
475         final quintptr is_shared(quintptr value)
476         {
477             bitfield = (bitfield & ~0x1) | ((value & 0x1) << 0);
478             return value;
479         }
480         /+ quintptr is_null : 1; +/
481         final quintptr is_null() const
482         {
483             return (bitfield >> 1) & 0x1;
484         }
485         final quintptr is_null(quintptr value)
486         {
487             bitfield = (bitfield & ~0x2) | ((value & 0x1) << 1);
488             return value;
489         }
490         /+ quintptr packedType : sizeof(QMetaType) * 8 - 2; +/
491         final quintptr packedType() const
492         {
493             return (bitfield >> 2) & 0x1;
494         }
495         final quintptr packedType(quintptr value)
496         {
497             bitfield = (bitfield & ~0x4) | ((value & 0x1) << 2);
498             return value;
499         }
500 
501         //@disable this();
502         /+this()/+ noexcept+/
503         {
504             this.is_shared = false;
505             this.is_null = true;
506             this.packedType = 0;
507         }+/
508         /+ explicit +/this(QMetaType type)/+ noexcept+/
509         {
510             this.is_shared = false;
511             this.is_null = false;
512 
513             quintptr mt = cast(quintptr)(type.d_ptr);
514             (mixin(Q_ASSERT(q{(mt & 0x3) == 0})));
515             packedType = mt >> 2;
516         }
517         /+ explicit +/this(int type)/+ noexcept+/
518         {
519             this(QMetaType(type));
520         }
521 
522         const(void)* storage() const return
523         { return is_shared ? data.shared_.data() : &data.data; }
524 
525         const(void)* internalStorage() const return
526         { (mixin(Q_ASSERT(q{QVariant.Private.is_shared}))); return &data.data; }
527 
528         // determine internal storage at compile time
529         /+ template<typename T> +/
530         ref const(T) get(T)() const
531         { return *static_cast!(const(T)*)(storage()); }
532         /+ template<typename T> +/
533         void set(T)(ref const(T) t)
534         { *static_cast!(T*)(CanUseInternalSpace!(T) ? &data.data : data.shared_.data()) = t; }
535 
536         pragma(inline, true) QMetaType type() const
537         {
538             return QMetaType(reinterpret_cast!(/+ QtPrivate:: +/qt.core.metatype.QMetaTypeInterface*)(packedType << 2));
539         }
540 
541         pragma(inline, true) /+ QtPrivate:: +/qt.core.metatype.QMetaTypeInterface*  typeInterface() const
542         {
543             return reinterpret_cast!(/+ QtPrivate:: +/qt.core.metatype.QMetaTypeInterface*)(packedType << 2);
544         }
545 
546         pragma(inline, true) int typeId() const
547         {
548             return type().id();
549         }
550     }
551  public:
552     static QPartialOrdering compare(ref const(QVariant) lhs, ref const(QVariant) rhs);
553 
554 private:
555     /+ friend inline bool operator==(const QVariant &a, const QVariant &b)
556     { return a.equals(b); } +/
557     /+ friend inline bool operator!=(const QVariant &a, const QVariant &b)
558     { return !a.equals(b); } +/
559 /+ #ifndef QT_NO_DEBUG_STREAM
560     template <typename T>
561     friend auto operator<<(const QDebug &debug, const T &variant) -> std::enable_if_t<std::is_same_v<T, QVariant>, QDebug> {
562         return  variant.qdebugHelper(debug);
563     }
564     QDebug qdebugHelper(QDebug) const;
565 #endif +/
566     /+ template<typename T> +/
567     /+ friend inline T qvariant_cast(const QVariant &); +/
568 protected:
569     Private d;
570     /+ void create(int type, const void *copy); +/
571     /+ void create(QMetaType type, const void *copy); +/
572     bool equals(ref const(QVariant) other) const;
573     bool convert(int type, void* ptr) const;
574     bool view(int type, void* ptr);
575 
576 private:
577     // force compile error, prevent QVariant(bool) to be called
578     pragma(inline, true) @disable this(void* ) /+ = delete +/;
579     // QVariant::Type is marked as \obsolete, but we don't want to
580     // provide a constructor from its intended replacement,
581     // QMetaType::Type, instead, because the idea behind these
582     // constructors is flawed in the first place. But we also don't
583     // want QVariant(QMetaType::String) to compile and falsely be an
584     // int variant, so delete this constructor:
585     @disable this(QMetaType.Type) /+ = delete +/;
586 
587     // These constructors don't create QVariants of the type associated
588     // with the enum, as expected, but they would create a QVariant of
589     // type int with the value of the enum value.
590     // Use QVariant v = QColor(Qt::red) instead of QVariant v = Qt::red for
591     // example.
592     @disable this(/+ Qt:: +/qt.core.namespace.GlobalColor) /+ = delete +/;
593     @disable this(/+ Qt:: +/qt.core.namespace.BrushStyle) /+ = delete +/;
594     @disable this(/+ Qt:: +/qt.core.namespace.PenStyle) /+ = delete +/;
595     @disable this(/+ Qt:: +/qt.core.namespace.CursorShape) /+ = delete +/;
596 /+ #ifdef QT_NO_CAST_FROM_ASCII +/
597     // force compile error when implicit conversion is not wanted
598     pragma(inline, true) @disable this(const(char)* ) /+ = delete +/;
599 /+ #endif +/
600 public:
601     alias DataPtr = Private;
602     pragma(inline, true) ref DataPtr data_ptr() return { return d; }
603     pragma(inline, true) ref const(DataPtr) data_ptr() const return { return d; }
604     mixin(CREATE_CONVENIENCE_WRAPPERS);
605 }
606 
607 /+ template<>
608 #if __has_include(<variant>) && __cplusplus >= 201703L
609 template<>
610 inline QVariant QVariant::fromValue(const std::monostate &)
611 {
612     return QVariant();
613 }
614 #endif
615 
616 #ifndef QT_NO_DATASTREAM
617 Q_CORE_EXPORT QDataStream &operator>>(QDataStream &s, QVariant &p);
618 Q_CORE_EXPORT QDataStream &operator<<(QDataStream &s, const QVariant &p);
619 
620 #if QT_DEPRECATED_SINCE(6, 0)
621 QT_WARNING_PUSH
622 QT_WARNING_DISABLE_DEPRECATED
623 QT_DEPRECATED_VERSION_6_0
624 inline QDataStream &operator>>(QDataStream &s, QVariant::Type &p)
625 {
626     quint32 u;
627     s >> u;
628     p = static_cast<QVariant::Type>(u);
629     return s;
630 }
631 QT_DEPRECATED_VERSION_6_0
632 inline QDataStream &operator<<(QDataStream &s, const QVariant::Type p)
633 {
634     s << static_cast<quint32>(p);
635     return s;
636 }
637 QT_WARNING_POP
638 #endif
639 
640 #endif
641 
642 Q_DECLARE_SHARED(QVariant) +/
643 
644 version(QT_MOC){}else
645 {
646 
647 /+pragma(inline, true) T qvariant_cast(T)(ref const(QVariant) v)
648 {
649     QMetaType targetType = QMetaType.fromType!(T)();
650     if (v.d.type() == targetType)
651         return v.d.get<TT>();
652     static if (/+ std:: +/is_same_v!(T,const(/+ std:: +/remove_const_t!(/+ std:: +/remove_pointer_t!(T)))*)) {
653         alias nonConstT = /+ std:: +/remove_const_t!(/+ std:: +/remove_pointer_t!(T))*;
654         QMetaType nonConstTargetType = QMetaType.fromType!(nonConstT)();
655         if (v.d.type() == nonConstTargetType)
656             return v.d.get<nonConstTnonConstT>();
657     }
658 
659     T t T();
660     QMetaType.convert(v.metaType(), v.constData(), targetType, &t);
661     return t;
662 }
663 
664 /+ template<> +/ 
665 pragma(inline, true) QVariant qvariant_cast(ref const(QVariant) v)
666 {
667     if (v.metaType().id() == QMetaType.Type.QVariant)
668         return *reinterpret_cast!(const(QVariant)*)(v.constData());
669     return v;
670 }+/
671 
672 }
673 
674 /+ #ifndef QT_NO_DEBUG_STREAM
675 #if QT_DEPRECATED_SINCE(6, 0)
676 QT_WARNING_PUSH
677 QT_WARNING_DISABLE_DEPRECATED
678 QT_DEPRECATED_VERSION_6_0
679 Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type);
680 QT_WARNING_POP
681 #endif
682 #endif +/
683 
684 extern(C++, "QtPrivate") {
685 extern(C++, class) struct /+ Q_CORE_EXPORT +/ QVariantTypeCoercer
686 {
687 public:
688     const(void)* convert(ref const(QVariant) value, ref const(QMetaType) type);
689     const(void)* coerce(ref const(QVariant) value, ref const(QMetaType) type);
690 
691 private:
692     QVariant converted;
693 }
694 }
695 
696 /// Binding for C++ class [QVariantRef](https://doc.qt.io/qt-6/qvariantref.html).
697 extern(C++, class) struct QVariantRef(Pointer)
698 {
699 private:
700     const(Pointer)* m_pointer = null;
701 
702 public:
703     /+ explicit +/this(const(Pointer)* reference)
704     {
705         this.m_pointer = reference;
706     }
707     /+ QVariantRef(const QVariantRef &) = default; +/
708     /+ QVariantRef(QVariantRef &&) = default; +/
709     /+ ~QVariantRef() = default; +/
710 
711     /+auto opCast(T : QVariant)() const;+/
712     /+ref QVariantRef operator =(ref const(QVariant) value);+/
713     /+ref QVariantRef operator =(ref const(QVariantRef) value) { return operator=(QVariant(value)); }+/
714     /+ QVariantRef &operator=(QVariantRef &&value) { return operator=(QVariant(value)); } +/
715 
716     /+ friend void swap(QVariantRef a, QVariantRef b)
717     {
718         QVariant tmp = a;
719         a = b;
720         b = std::move(tmp);
721     } +/
722 }
723 
724 /// Binding for C++ class [QVariantConstPointer](https://doc.qt.io/qt-6/qvariantconstpointer.html).
725 extern(C++, class) struct /+ Q_CORE_EXPORT +/ QVariantConstPointer
726 {
727 private:
728     QVariant m_variant;
729 
730 public:
731     /+ explicit +/this(QVariant variant);
732 
733     QVariant opUnary(string op)() const if(op == "*");
734     /+const(QVariant)* operator ->() const;+/
735     mixin(CREATE_CONVENIENCE_WRAPPERS);
736 }
737 
738 /// Binding for C++ class [QVariantPointer](https://doc.qt.io/qt-6/qvariantpointer.html).
739 class QVariantPointer(Pointer)
740 {
741 private:
742     const(Pointer)* m_pointer = null;
743 
744 public:
745     /+ explicit +/this(const(Pointer)* pointer)
746     {
747         this.m_pointer = pointer;
748     }
749     //final QVariantRef!(Pointer) opUnary(string op)() const if(op == "*") { return QVariantRef!(Pointer)(cast(QVariantRef && )(m_pointer)); }
750     /+final Pointer operator ->() const { return *m_pointer; }+/
751 }
752 
753 pragma(inline, true) T qvariant_cast(T)(ref const(QVariant) v)
754 {
755     // TODO: special cases of qvariant_cast
756     static if(is(T == class))
757         static assert(false);
758     else
759     {
760         const(int) vid = qMetaTypeId!(T)();
761         if (vid == v.userType())
762             return *reinterpret_cast!(T*)(v.constData());
763         static if(__traits(hasMember, T, "rawConstructor"))
764             mixin("T t = T.init; t.rawConstructor();");
765         else
766             mixin("T t;");
767         if (v.convert(vid, &t))
768             return t;
769         static if(__traits(hasMember, T, "rawConstructor"))
770             mixin("T r = T.init; r.rawConstructor(); return r;");
771         else
772             mixin("return T();");
773     }
774 }
775 pragma(inline, true) T qvariant_cast(T)(const(QVariant) v)
776 {
777     return qvariant_cast!T(v);
778 }
779