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