Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qvariant.h
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QVARIANT_H
5#define QVARIANT_H
6
7#include <QtCore/qatomic.h>
8#include <QtCore/qcompare.h>
9#include <QtCore/qcontainerfwd.h>
10#include <QtCore/qmetatype.h>
11#ifndef QT_NO_DEBUG_STREAM
12#include <QtCore/qdebug.h>
13#endif
14
15#include <memory>
16#include <QtCore/q20type_traits.h>
17#include <QtCore/q23utility.h>
18#include <variant>
19
20#if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 1
21# include <QtCore/qlist.h>
22# include <QtCore/qstringlist.h>
23# include <QtCore/qbytearraylist.h>
24# include <QtCore/qhash.h>
25# include <QtCore/qmap.h>
26# include <QtCore/qobject.h>
27#endif
28
29QT_BEGIN_NAMESPACE
30
31QT_ENABLE_P0846_SEMANTICS_FOR(get_if)
32QT_ENABLE_P0846_SEMANTICS_FOR(get)
33
34class QBitArray;
35class QDataStream;
36class QDate;
37class QDateTime;
38class QEasingCurve;
39class QLine;
40class QLineF;
41class QLocale;
42class QModelIndex;
43class QPersistentModelIndex;
44class QPoint;
45class QPointF;
46class QRect;
47class QRectF;
48class QRegularExpression;
49class QSize;
50class QSizeF;
51class QTextFormat;
52class QTextLength;
53class QTime;
54class QTransform;
55class QUrl;
56class QVariant;
57
58template<typename T>
59inline T qvariant_cast(const QVariant &);
60
61namespace QtPrivate {
62template<> constexpr inline bool qIsRelocatable<QVariant> = true;
63}
64class Q_CORE_EXPORT QVariant
65{
66 template <typename T, typename... Args>
67 using if_constructible = std::enable_if_t<
68 std::conjunction_v<
69 std::is_copy_constructible<q20::remove_cvref_t<T>>,
70 std::is_destructible<q20::remove_cvref_t<T>>,
71 std::is_constructible<q20::remove_cvref_t<T>, Args...>
72 >,
73 bool>;
74
75 template <typename T>
76 using if_rvalue = std::enable_if_t<!std::is_reference_v<T>, bool>;
77
78 struct CborValueStandIn { qint64 n; void *c; int t; };
79public:
80 struct PrivateShared
81 {
82 private:
83 inline PrivateShared() : ref(1) { }
84 public:
85 static int computeOffset(PrivateShared *ps, size_t align);
86 static size_t computeAllocationSize(size_t size, size_t align);
87 static PrivateShared *create(size_t size, size_t align);
88 static void free(PrivateShared *p);
89
90 alignas(8) QAtomicInt ref;
91 int offset;
92
93 const void *data() const { return reinterpret_cast<const uchar *>(this) + offset; }
94 void *data() { return reinterpret_cast<uchar *>(this) + offset; }
95 };
96
97 struct Private
98 {
99 static constexpr size_t MaxInternalSize = 3 * sizeof(void *);
100 template <size_t S> static constexpr bool FitsInInternalSize = S <= MaxInternalSize;
101 template<typename T> static constexpr bool CanUseInternalSpace =
102 (QTypeInfo<T>::isRelocatable && FitsInInternalSize<sizeof(T)> && alignof(T) <= alignof(double));
103 static constexpr bool canUseInternalSpace(const QtPrivate::QMetaTypeInterface *type)
104 {
105 Q_ASSERT(type);
106 return QMetaType::TypeFlags(type->flags) & QMetaType::RelocatableType &&
107 size_t(type->size) <= MaxInternalSize && size_t(type->alignment) <= alignof(double);
108 }
109
110 union
111 {
112 uchar data[MaxInternalSize] = {};
113 PrivateShared *shared;
114 double _forAlignment; // we want an 8byte alignment on 32bit systems as well
115 } data;
116 quintptr is_shared : 1;
117 quintptr is_null : 1;
118 quintptr packedType : sizeof(QMetaType) * 8 - 2;
119
120 constexpr Private() noexcept : is_shared(false), is_null(true), packedType(0) {}
121 explicit Private(const QtPrivate::QMetaTypeInterface *iface) noexcept;
122 template <typename T> explicit Private(std::piecewise_construct_t, const T &t);
123
124 const void *storage() const
125 { return is_shared ? data.shared->data() : &data.data; }
126
127 template<typename T> const T &get() const
128 { return *static_cast<const T *>(storage()); }
129
130 inline const QtPrivate::QMetaTypeInterface *typeInterface() const
131 {
132 return reinterpret_cast<const QtPrivate::QMetaTypeInterface *>(packedType << 2);
133 }
134
135 inline QMetaType type() const
136 {
137 return QMetaType(typeInterface());
138 }
139 };
140
141#if QT_DEPRECATED_SINCE(6, 0)
142 enum QT_DEPRECATED_VERSION_X_6_0("Use QMetaType::Type instead.") Type
143 {
144 Invalid = QMetaType::UnknownType,
145 Bool = QMetaType::Bool,
146 Int = QMetaType::Int,
147 UInt = QMetaType::UInt,
148 LongLong = QMetaType::LongLong,
149 ULongLong = QMetaType::ULongLong,
150 Double = QMetaType::Double,
151 Char = QMetaType::QChar,
152 Map = QMetaType::QVariantMap,
153 List = QMetaType::QVariantList,
154 String = QMetaType::QString,
155 StringList = QMetaType::QStringList,
156 ByteArray = QMetaType::QByteArray,
157 BitArray = QMetaType::QBitArray,
158 Date = QMetaType::QDate,
159 Time = QMetaType::QTime,
160 DateTime = QMetaType::QDateTime,
161 Url = QMetaType::QUrl,
162 Locale = QMetaType::QLocale,
163 Rect = QMetaType::QRect,
164 RectF = QMetaType::QRectF,
165 Size = QMetaType::QSize,
166 SizeF = QMetaType::QSizeF,
167 Line = QMetaType::QLine,
168 LineF = QMetaType::QLineF,
169 Point = QMetaType::QPoint,
170 PointF = QMetaType::QPointF,
171#if QT_CONFIG(regularexpression)
172 RegularExpression = QMetaType::QRegularExpression,
173#endif
174 Hash = QMetaType::QVariantHash,
175#if QT_CONFIG(easingcurve)
176 EasingCurve = QMetaType::QEasingCurve,
177#endif
178 Uuid = QMetaType::QUuid,
179#if QT_CONFIG(itemmodel)
180 ModelIndex = QMetaType::QModelIndex,
181 PersistentModelIndex = QMetaType::QPersistentModelIndex,
182#endif
183 LastCoreType = QMetaType::LastCoreType,
184
185 Font = QMetaType::QFont,
186 Pixmap = QMetaType::QPixmap,
187 Brush = QMetaType::QBrush,
188 Color = QMetaType::QColor,
189 Palette = QMetaType::QPalette,
190 Image = QMetaType::QImage,
191 Polygon = QMetaType::QPolygon,
192 Region = QMetaType::QRegion,
193 Bitmap = QMetaType::QBitmap,
194 Cursor = QMetaType::QCursor,
195#if QT_CONFIG(shortcut)
196 KeySequence = QMetaType::QKeySequence,
197#endif
198 Pen = QMetaType::QPen,
199 TextLength = QMetaType::QTextLength,
200 TextFormat = QMetaType::QTextFormat,
201 Transform = QMetaType::QTransform,
202 Matrix4x4 = QMetaType::QMatrix4x4,
203 Vector2D = QMetaType::QVector2D,
204 Vector3D = QMetaType::QVector3D,
205 Vector4D = QMetaType::QVector4D,
206 Quaternion = QMetaType::QQuaternion,
207 PolygonF = QMetaType::QPolygonF,
208 Icon = QMetaType::QIcon,
209 LastGuiType = QMetaType::LastGuiType,
210
211 SizePolicy = QMetaType::QSizePolicy,
212
213 UserType = QMetaType::User,
214 LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type
215 };
216#endif
217 QVariant() noexcept : d() {}
218 ~QVariant();
219 explicit QVariant(QMetaType type, const void *copy = nullptr);
220 QVariant(const QVariant &other);
221
222private:
223 template <typename T, typename ...Args>
224 using is_noexcept_constructible = std::conjunction<
225 std::bool_constant<Private::CanUseInternalSpace<T>>,
226 std::is_nothrow_constructible<T, Args...>
227 >;
228
229public:
230 template <typename T, typename... Args,
231 if_constructible<T, Args...> = true>
232 explicit QVariant(std::in_place_type_t<T>, Args&&... args)
233 noexcept(is_noexcept_constructible<q20::remove_cvref_t<T>, Args...>::value)
234 : QVariant(std::in_place, QMetaType::fromType<q20::remove_cvref_t<T>>() )
235 {
236 void *data = const_cast<void *>(constData());
237 new (data) T(std::forward<Args>(args)...);
238 }
239
240 template <typename T, typename U, typename... Args,
241 if_constructible<T, std::initializer_list<U> &, Args...> = true>
242 explicit QVariant(std::in_place_type_t<T>, std::initializer_list<U> il, Args&&... args)
243 noexcept(is_noexcept_constructible<q20::remove_cvref_t<T>,
244 std::initializer_list<U> &,
245 Args...
246 >::value)
247 : QVariant(std::in_place, QMetaType::fromType<q20::remove_cvref_t<T>>())
248 {
249 char *data = static_cast<char *>(const_cast<void *>(constData()));
250 new (data) T(il, std::forward<Args>(args)...);
251 }
252
253 // primitives
254 QVariant(int i) noexcept;
255 QVariant(uint ui) noexcept;
256 QVariant(qlonglong ll) noexcept;
257 QVariant(qulonglong ull) noexcept;
258 QVariant(bool b) noexcept;
259 QVariant(double d) noexcept;
260 QVariant(float f) noexcept;
261
262 // trivial, trivially-copyable or COW
263 QVariant(QChar qchar) noexcept;
264 QVariant(QDate date) noexcept;
265 QVariant(QTime time) noexcept;
266 QVariant(const QBitArray &bitarray) noexcept;
267 QVariant(const QByteArray &bytearray) noexcept;
268 QVariant(const QDateTime &datetime) noexcept;
269 QVariant(const QHash<QString, QVariant> &hash) noexcept;
270 QVariant(const QJsonArray &jsonArray) noexcept;
271 QVariant(const QJsonObject &jsonObject) noexcept;
272 QVariant(const QList<QVariant> &list) noexcept;
273 QVariant(const QLocale &locale) noexcept;
274 QVariant(const QMap<QString, QVariant> &map) noexcept;
275 QVariant(const QRegularExpression &re) noexcept;
276 QVariant(const QString &string) noexcept;
277 QVariant(const QStringList &stringlist) noexcept;
278 QVariant(const QUrl &url) noexcept;
279
280 // conditionally noexcept trivial or trivially-copyable
281 // (most of these are noexcept on 64-bit)
282 QVariant(const QJsonValue &jsonValue) noexcept(Private::FitsInInternalSize<sizeof(CborValueStandIn)>);
283 QVariant(const QModelIndex &modelIndex) noexcept(Private::FitsInInternalSize<8 + 2 * sizeof(quintptr)>);
284 QVariant(QUuid uuid) noexcept(Private::FitsInInternalSize<16>);
285 QVariant(QSize size) noexcept;
286 QVariant(QSizeF size) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>);
287 QVariant(QPoint pt) noexcept;
288 QVariant(QPointF pt) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>);
289 QVariant(QLine line) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>);
290 QVariant(QLineF line) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>);
291 QVariant(QRect rect) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>);
292 QVariant(QRectF rect) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>);
293
294 // not noexcept
295 QVariant(const QEasingCurve &easing) noexcept(false);
296 QVariant(const QJsonDocument &jsonDocument) noexcept(false);
297 QVariant(const QPersistentModelIndex &modelIndex) noexcept(false);
298
299#ifndef QT_NO_CAST_FROM_ASCII
300 QT_ASCII_CAST_WARN QVariant(const char *str) noexcept(false)
301 : QVariant(QString::fromUtf8(str))
302 {}
303#endif
304 QVariant(QLatin1StringView string) noexcept(false); // converts to QString
305
306#if !defined(Q_CC_GHS)
307 // GHS has an ICE with this code; use the simplified version below
308 template <typename T,
309 std::enable_if_t<std::disjunction_v<std::is_pointer<T>, std::is_member_pointer<T>>, bool> = false>
310 QVariant(T) = delete;
311#else
312 QVariant(const volatile void *) = delete;
313#endif
314
315#if QT_CORE_REMOVED_SINCE(6, 5)
316 QVariant(const QSize &size);
317 QVariant(const QSizeF &size);
318 QVariant(const QPoint &pt);
319 QVariant(const QPointF &pt);
320 QVariant(const QLine &line);
321 QVariant(const QLineF &line);
322 QVariant(const QRect &rect);
323 QVariant(const QRectF &rect);
324 QVariant(const QUuid &uuid);
325#endif
326
327 QVariant& operator=(const QVariant &other);
328 inline QVariant(QVariant &&other) noexcept : d(other.d)
329 { other.d = Private(); }
330 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QVariant)
331
332 inline void swap(QVariant &other) noexcept { std::swap(d, other.d); }
333
334 int userType() const { return typeId(); }
335 int typeId() const { return metaType().id(); }
336
337 const char *typeName() const;
338 QMetaType metaType() const;
339
340 bool canConvert(QMetaType targetType) const
341 { return QMetaType::canConvert(d.type(), targetType); }
342 bool convert(QMetaType type);
343
344 bool canView(QMetaType targetType) const
345 { return QMetaType::canView(d.type(), targetType); }
346
347#if QT_DEPRECATED_SINCE(6, 0)
348 QT_DEPRECATED_VERSION_6_0
349 bool canConvert(int targetTypeId) const
350 { return QMetaType::canConvert(d.type(), QMetaType(targetTypeId)); }
351 QT_DEPRECATED_VERSION_6_0
352 bool convert(int targetTypeId)
353 { return convert(QMetaType(targetTypeId)); }
354#endif
355
356 inline bool isValid() const;
357 bool isNull() const;
358
359 void clear();
360
361 void detach();
362 inline bool isDetached() const;
363
364 int toInt(bool *ok = nullptr) const;
365 uint toUInt(bool *ok = nullptr) const;
366 qlonglong toLongLong(bool *ok = nullptr) const;
367 qulonglong toULongLong(bool *ok = nullptr) const;
368 bool toBool() const;
369 double toDouble(bool *ok = nullptr) const;
370 float toFloat(bool *ok = nullptr) const;
371 qreal toReal(bool *ok = nullptr) const;
372 QByteArray toByteArray() const;
373 QBitArray toBitArray() const;
374 QString toString() const;
375 QStringList toStringList() const;
376 QChar toChar() const;
377 QDate toDate() const;
378 QTime toTime() const;
379 QDateTime toDateTime() const;
380 QList<QVariant> toList() const;
381 QMap<QString, QVariant> toMap() const;
382 QHash<QString, QVariant> toHash() const;
383
384 QPoint toPoint() const;
385 QPointF toPointF() const;
386 QRect toRect() const;
387 QSize toSize() const;
388 QSizeF toSizeF() const;
389 QLine toLine() const;
390 QLineF toLineF() const;
391 QRectF toRectF() const;
392 QLocale toLocale() const;
393#if QT_CONFIG(regularexpression)
394 QRegularExpression toRegularExpression() const;
395#endif // QT_CONFIG(regularexpression)
396#if QT_CONFIG(easingcurve)
397 QEasingCurve toEasingCurve() const;
398#endif
399 QUuid toUuid() const;
400 QUrl toUrl() const;
401 QJsonValue toJsonValue() const;
402 QJsonObject toJsonObject() const;
403 QJsonArray toJsonArray() const;
404 QJsonDocument toJsonDocument() const;
405#if QT_CONFIG(itemmodel)
406 QModelIndex toModelIndex() const;
407 QPersistentModelIndex toPersistentModelIndex() const;
408#endif
409
410#ifndef QT_NO_DATASTREAM
411 void load(QDataStream &ds);
412 void save(QDataStream &ds) const;
413#endif
414#if QT_DEPRECATED_SINCE(6, 0)
415 QT_WARNING_PUSH
416 QT_WARNING_DISABLE_DEPRECATED
417 QT_DEPRECATED_VERSION_X_6_0("Use the constructor taking a QMetaType instead.")
418 explicit QVariant(Type type)
419 : QVariant(QMetaType(int(type)))
420 {}
421 QT_DEPRECATED_VERSION_X_6_0("Use typeId() or metaType().")
422 Type type() const
423 {
424 int type = d.type().id();
425 return type >= QMetaType::User ? UserType : static_cast<Type>(type);
426 }
427 QT_DEPRECATED_VERSION_6_0
428 static const char *typeToName(int typeId)
429 { return QMetaType(typeId).name(); }
430 QT_DEPRECATED_VERSION_6_0
431 static Type nameToType(const char *name)
432 {
433 int metaType = QMetaType::fromName(name).id();
434 return metaType <= int(UserType) ? QVariant::Type(metaType) : UserType;
435 }
436 QT_WARNING_POP
437#endif
438
439 void *data();
440 const void *constData() const
441 { return d.storage(); }
442 inline const void *data() const { return constData(); }
443
444private:
445 template <typename T>
446 void verifySuitableForEmplace()
447 {
448 static_assert(!std::is_reference_v<T>,
449 "QVariant does not support reference types");
450 static_assert(!std::is_const_v<T>,
451 "QVariant does not support const types");
452 static_assert(std::is_copy_constructible_v<T>,
453 "QVariant requires that the type is copyable");
454 static_assert(std::is_destructible_v<T>,
455 "QVariant requires that the type is destructible");
456 }
457
458 template <typename T, typename... Args>
459 T &emplaceImpl(Args&&... args)
460 {
461 verifySuitableForEmplace<T>();
462 auto data = static_cast<T *>(prepareForEmplace(QMetaType::fromType<T>()));
463 return *q20::construct_at(data, std::forward<Args>(args)...);
464 }
465
466public:
467 template <typename T, typename... Args,
468 if_constructible<T, Args...> = true>
469 T &emplace(Args&&... args)
470 {
471 return emplaceImpl<T>(std::forward<Args>(args)...);
472 }
473
474 template <typename T, typename U, typename... Args,
475 if_constructible<T, std::initializer_list<U> &, Args...> = true>
476 T &emplace(std::initializer_list<U> list, Args&&... args)
477 {
478 return emplaceImpl<T>(list, std::forward<Args>(args)...);
479 }
480
481 template<typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, QVariant>>>
482 void setValue(T &&avalue)
483 {
484 using VT = std::decay_t<T>;
485 QMetaType metaType = QMetaType::fromType<VT>();
486 // If possible we reuse the current QVariant private.
487 if (isDetached() && d.type() == metaType) {
488 *reinterpret_cast<VT *>(const_cast<void *>(constData())) = std::forward<T>(avalue);
489 d.is_null = false;
490 } else {
491 *this = QVariant::fromValue<VT>(std::forward<T>(avalue));
492 }
493 }
494
495 void setValue(const QVariant &avalue)
496 {
497 *this = avalue;
498 }
499
500 void setValue(QVariant &&avalue)
501 {
502 *this = std::move(avalue);
503 }
504
505 template<typename T>
506 inline T value() const &
507 { return qvariant_cast<T>(*this); }
508
509 template<typename T>
510 inline T view()
511 {
512 T t{};
513 QMetaType::view(metaType(), data(), QMetaType::fromType<T>(), &t);
514 return t;
515 }
516
517 template<typename T>
518 inline T value() &&
519 { return qvariant_cast<T>(std::move(*this)); }
520
521 template<typename T, if_rvalue<T> = true>
522#ifndef Q_QDOC
523 /* needs is_copy_constructible for variants semantics, is_move_constructible so that moveConstruct works
524 (but copy_constructible implies move_constructble, so don't bother checking)
525 */
526 static inline auto fromValue(T &&value)
527 noexcept(std::is_nothrow_copy_constructible_v<T> && Private::CanUseInternalSpace<T>)
528 -> std::enable_if_t<std::conjunction_v<std::is_copy_constructible<T>,
529 std::is_destructible<T>>, QVariant>
530#else
531 static inline QVariant fromValue(T &&value)
532#endif
533 {
534 // handle special cases
535 using Type = std::remove_cv_t<T>;
536 if constexpr (std::is_null_pointer_v<Type>)
537 return QVariant::fromMetaType(QMetaType::fromType<std::nullptr_t>());
538 else if constexpr (std::is_same_v<Type, QVariant>)
539 return std::forward<T>(value);
540 else if constexpr (std::is_same_v<Type, std::monostate>)
541 return QVariant();
542 QMetaType mt = QMetaType::fromType<Type>();
543 mt.registerType(); // we want the type stored in QVariant to always be registered
544
545 // We only try to move if the type is actually moveable and not if T is const
546 // as in const int i; QVariant::fromValue(std::move(i));
547 if constexpr (std::conjunction_v<std::is_move_constructible<Type>, std::negation<std::is_const<T>>>)
548 return moveConstruct(QMetaType::fromType<Type>(), std::addressof(value));
549 else
550 return copyConstruct(mt, std::addressof(value));
551 }
552
553 template<typename T>
554#ifndef Q_QDOC
555 static inline auto fromValue(const T &value)
556 noexcept(std::is_nothrow_copy_constructible_v<T> && Private::CanUseInternalSpace<T>)
557 -> std::enable_if_t<std::is_copy_constructible_v<T> && std::is_destructible_v<T>, QVariant>
558#else
559 static inline QVariant fromValue(const T &value)
560#endif
561 {
562 if constexpr (std::is_null_pointer_v<T>)
563 return QVariant(QMetaType::fromType<std::nullptr_t>());
564 else if constexpr (std::is_same_v<T, QVariant>)
565 return value;
566 else if constexpr (std::is_same_v<T, std::monostate>)
567 return QVariant();
568 return QVariant(QMetaType::fromType<T>(), std::addressof(value));
569 }
570
571 template<typename... Types>
572 static inline QVariant fromStdVariant(const std::variant<Types...> &value)
573 {
574 return fromStdVariantImpl(value);
575 }
576
577 template<typename... Types>
578 static QVariant fromStdVariant(std::variant<Types...> &&value)
579 {
580 return fromStdVariantImpl(std::move(value));
581 }
582
583 static QVariant fromMetaType(QMetaType type, const void *copy = nullptr);
584
585 template<typename T>
586 bool canConvert() const
587 { return canConvert(QMetaType::fromType<T>()); }
588
589 template<typename T>
590 bool canView() const
591 { return canView(QMetaType::fromType<T>()); }
592
593 static QPartialOrdering compare(const QVariant &lhs, const QVariant &rhs);
594
595private:
596 template <typename StdVariant>
597 static QVariant fromStdVariantImpl(StdVariant &&v)
598 {
599 if (Q_UNLIKELY(v.valueless_by_exception()))
600 return QVariant();
601 auto visitor = [](auto &&arg) {
602 return QVariant::fromValue(q23::forward_like<StdVariant>(arg));
603 };
604 return std::visit(visitor, std::forward<StdVariant>(v));
605 }
606
607 friend bool comparesEqual(const QVariant &a, const QVariant &b)
608 { return a.equals(b); }
609 Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(QVariant)
610
611#ifndef QT_NO_DEBUG_STREAM
612 template <typename T>
613 friend auto operator<<(const QDebug &debug, const T &variant) -> std::enable_if_t<std::is_same_v<T, QVariant>, QDebug> {
614 return variant.qdebugHelper(debug);
615 }
616 QDebug qdebugHelper(QDebug) const;
617#endif
618
619 template <typename T>
620 friend T *get_if(QVariant *v) noexcept
621 {
622 // data() will detach from is_null, returning non-nullptr
623 if (!v || v->d.type() != QMetaType::fromType<T>())
624 return nullptr;
625 return static_cast<T*>(v->data());
626 }
627 template <typename T>
628 friend const T *get_if(const QVariant *v) noexcept
629 {
630 // (const) data() will not detach from is_null, return nullptr
631 if (!v || v->d.is_null || v->d.type() != QMetaType::fromType<T>())
632 return nullptr;
633 return static_cast<const T*>(v->data());
634 }
635
636#define Q_MK_GET(cvref)
637 template <typename T>
638 friend T cvref get(QVariant cvref v)
639 {
640 if constexpr (std::is_const_v<T cvref>)
641 Q_ASSERT(!v.d.is_null);
642 Q_ASSERT(v.d.type() == QMetaType::fromType<q20::remove_cvref_t<T>>());
643 return static_cast<T cvref>(*get_if<T>(&v));
644 }
645 /* end */
646 Q_MK_GET(&)
647 Q_MK_GET(const &)
648 Q_MK_GET(&&)
649 Q_MK_GET(const &&)
650#undef Q_MK_GET
651
652 static QVariant moveConstruct(QMetaType type, void *data);
653 static QVariant copyConstruct(QMetaType type, const void *data);
654
655 template<typename T>
656 friend inline T qvariant_cast(const QVariant &);
657 template<typename T>
658 friend inline T qvariant_cast(QVariant &&);
659
660protected:
661 Private d;
662 void create(int type, const void *copy);
663 void create(QMetaType type, const void *copy);
664 bool equals(const QVariant &other) const;
665 bool convert(int type, void *ptr) const;
666 bool view(int type, void *ptr);
667
668private:
669 // force compile error, prevent QVariant(bool) to be called
670 inline QVariant(void *) = delete;
671 // QVariant::Type is marked as \obsolete, but we don't want to
672 // provide a constructor from its intended replacement,
673 // QMetaType::Type, instead, because the idea behind these
674 // constructors is flawed in the first place. But we also don't
675 // want QVariant(QMetaType::String) to compile and falsely be an
676 // int variant, so delete this constructor:
677 QVariant(QMetaType::Type) = delete;
678
679 // used to setup the QVariant internals for the "real" inplace ctor
680 QVariant(std::in_place_t, QMetaType type);
681 // helper for emplace
682 void *prepareForEmplace(QMetaType type);
683
684 // These constructors don't create QVariants of the type associated
685 // with the enum, as expected, but they would create a QVariant of
686 // type int with the value of the enum value.
687 // Use QVariant v = QColor(Qt::red) instead of QVariant v = Qt::red for
688 // example.
689 QVariant(Qt::GlobalColor) = delete;
690 QVariant(Qt::BrushStyle) = delete;
691 QVariant(Qt::PenStyle) = delete;
692 QVariant(Qt::CursorShape) = delete;
693#ifdef QT_NO_CAST_FROM_ASCII
694 // force compile error when implicit conversion is not wanted
695 inline QVariant(const char *) = delete;
696#endif
697public:
698 typedef Private DataPtr;
699 inline DataPtr &data_ptr() { return d; }
700 inline const DataPtr &data_ptr() const { return d; }
701};
702
703inline bool QVariant::isValid() const
704{
705 return d.type().isValid(QT6_CALL_NEW_OVERLOAD);
706}
707
708#ifndef QT_NO_DATASTREAM
709Q_CORE_EXPORT QDataStream &operator>>(QDataStream &s, QVariant &p);
710Q_CORE_EXPORT QDataStream &operator<<(QDataStream &s, const QVariant &p);
711
712#if QT_DEPRECATED_SINCE(6, 0)
713QT_WARNING_PUSH
714QT_WARNING_DISABLE_DEPRECATED
715QT_DEPRECATED_VERSION_6_0
716inline QDataStream &operator>>(QDataStream &s, QVariant::Type &p)
717{
718 quint32 u;
719 s >> u;
720 p = static_cast<QVariant::Type>(u);
721 return s;
722}
723QT_DEPRECATED_VERSION_6_0
724inline QDataStream &operator<<(QDataStream &s, const QVariant::Type p)
725{
726 s << static_cast<quint32>(p);
727 return s;
728}
729QT_WARNING_POP
730#endif
731
732#endif
733
734inline bool QVariant::isDetached() const
735{ return !d.is_shared || d.data.shared->ref.loadRelaxed() == 1; }
736
737inline void swap(QVariant &value1, QVariant &value2) noexcept
738{ value1.swap(value2); }
739
740#ifndef QT_MOC
741
742template<typename T> inline T qvariant_cast(const QVariant &v)
743{
744 QMetaType targetType = QMetaType::fromType<T>();
745 if (v.d.type() == targetType)
746 return v.d.get<T>();
747 if constexpr (std::is_same_v<T,std::remove_const_t<std::remove_pointer_t<T>> const *>) {
748 using nonConstT = std::remove_const_t<std::remove_pointer_t<T>> *;
749 QMetaType nonConstTargetType = QMetaType::fromType<nonConstT>();
750 if (v.d.type() == nonConstTargetType)
751 return v.d.get<nonConstT>();
752 }
753
754 T t{};
755 QMetaType::convert(v.metaType(), v.constData(), targetType, &t);
756 return t;
757}
758
759template<typename T> inline T qvariant_cast(QVariant &&v)
760{
761 QMetaType targetType = QMetaType::fromType<T>();
762 if (v.d.type() == targetType) {
763 if (!v.d.is_shared) {
764 return std::move(*reinterpret_cast<T *>(v.d.data.data));
765 } else {
766 if (v.d.data.shared->ref.loadRelaxed() == 1)
767 return std::move(*reinterpret_cast<T *>(v.d.data.shared->data()));
768 else
769 return v.d.get<T>();
770 }
771 }
772 if constexpr (std::is_same_v<T, QVariant>) {
773 // if the metatype doesn't match, but we want a QVariant, just return the current variant
774 return v;
775 } if constexpr (std::is_same_v<T,std::remove_const_t<std::remove_pointer_t<T>> const *>) {
776 // moving a pointer is pointless, just do the same as the const & overload
777 using nonConstT = std::remove_const_t<std::remove_pointer_t<T>> *;
778 QMetaType nonConstTargetType = QMetaType::fromType<nonConstT>();
779 if (v.d.type() == nonConstTargetType)
780 return v.d.get<nonConstT>();
781 }
782
783 T t{};
784 QMetaType::convert(v.metaType(), v.constData(), targetType, &t);
785 return t;
786}
787
788# ifndef QT_NO_VARIANT
789template<> inline QVariant qvariant_cast<QVariant>(const QVariant &v)
790{
791 if (v.metaType().id() == QMetaType::QVariant)
792 return *reinterpret_cast<const QVariant *>(v.constData());
793 return v;
794}
795# endif
796
797#endif // QT_MOC
798
799#ifndef QT_NO_DEBUG_STREAM
800#if QT_DEPRECATED_SINCE(6, 0)
801QT_WARNING_PUSH
802QT_WARNING_DISABLE_DEPRECATED
803QT_DEPRECATED_VERSION_6_0
804Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type);
805QT_WARNING_POP
806#endif
807#endif
808
809namespace QtPrivate {
810class Q_CORE_EXPORT QVariantTypeCoercer
811{
812public:
813 // ### Qt7: Pass QMetaType as value rather than const ref.
814 const void *convert(const QVariant &value, const QMetaType &type);
815 const void *coerce(const QVariant &value, const QMetaType &type);
816
817private:
819};
820}
821
822template<typename Pointer>
824{
825private:
826 const Pointer *m_pointer = nullptr;
827
828public:
829 explicit QVariantRef(const Pointer *reference) : m_pointer(reference) {}
830 QVariantRef(const QVariantRef &) = default;
832 ~QVariantRef() = default;
833
834 operator QVariant() const;
835 QVariantRef &operator=(const QVariant &value);
836 QVariantRef &operator=(const QVariantRef &value) { return operator=(QVariant(value)); }
837 QVariantRef &operator=(QVariantRef &&value) { return operator=(QVariant(value)); }
838
839 friend void swap(QVariantRef a, QVariantRef b)
840 {
841 QVariant tmp = a;
842 a = b;
843 b = std::move(tmp);
844 }
845};
846
847class Q_CORE_EXPORT QVariantConstPointer
848{
849private:
850 QVariant m_variant;
851
852public:
853 explicit QVariantConstPointer(QVariant variant);
854
855 QVariant operator*() const;
856 const QVariant *operator->() const;
857};
858
859template<typename Pointer>
861{
862private:
863 const Pointer *m_pointer = nullptr;
864
865public:
866 explicit QVariantPointer(const Pointer *pointer) : m_pointer(pointer) {}
867 QVariantRef<Pointer> operator*() const { return QVariantRef<Pointer>(m_pointer); }
868 Pointer operator->() const { return *m_pointer; }
869};
870
871QT_END_NAMESPACE
872
873#endif // QVARIANT_H
\inmodule QtCore\reentrant
Definition qdatastream.h:49
\inmodule QtCore
\inmodule QtCore\reentrant
Definition qpoint.h:229
\inmodule QtCore\reentrant
Definition qpoint.h:28
Emulated const pointer to QVariant based on a pointer.
Definition qvariant.h:848
QVariantPointer is a template class that emulates a pointer to QVariant based on a pointer.
Definition qvariant.h:861
QVariantPointer(const Pointer *pointer)
Constructs a QVariantPointer from the given pointer.
Definition qvariant.h:866
QVariantRef< Pointer > operator*() const
Dereferences the QVariantPointer to a QVariantRef.
Definition qvariant.h:867
Pointer operator->() const
Dereferences and returns the pointer.
Definition qvariant.h:868
The QVariantRef acts as a non-const reference to a QVariant.
Definition qvariant.h:824
operator QVariant() const
Resolves the QVariantRef to an actual QVariant.
QVariantRef & operator=(const QVariantRef &value)
Assigns a new value to the value pointed to by the pointer this QVariantRef refers to.
Definition qvariant.h:836
QVariantRef & operator=(const QVariant &value)
Assigns a new value to the value pointed to by the pointer this QVariantRef refers to.
~QVariantRef()=default
QVariantRef(const QVariantRef &)=default
QVariantRef(QVariantRef &&)=default
friend void swap(QVariantRef a, QVariantRef b)
Definition qvariant.h:839
QVariantRef & operator=(QVariantRef &&value)
Assigns a new value to the value pointed to by the pointer this QVariantRef refers to.
Definition qvariant.h:837
QVariantRef(const Pointer *reference)
Creates a QVariantRef from an pointer.
Definition qvariant.h:829
\inmodule QtCore
Definition qvariant.h:65
Combined button and popup list for selecting options.
static QString appendSlashIfNeeded(const QString &path)
#define Q_MK_GET(cvref)
Definition qvariant.h:636
T qvariant_cast(QVariant &&v)
Definition qvariant.h:759
T qvariant_cast(const QVariant &)
Definition qvariant.h:742
void swap(QVariant &value1, QVariant &value2) noexcept
Definition qvariant.h:737