Qt 6.x
The Qt SDK
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/qcontainerfwd.h>
9#include <QtCore/qmetatype.h>
10#ifndef QT_NO_DEBUG_STREAM
11#include <QtCore/qdebug.h>
12#endif
13
14#include <memory>
15#include <QtCore/q20type_traits.h>
16#include <QtCore/q23utility.h>
17#include <variant>
18
19#if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 1
20# include <QtCore/qlist.h>
21# include <QtCore/qstringlist.h>
22# include <QtCore/qbytearraylist.h>
23# include <QtCore/qhash.h>
24# include <QtCore/qmap.h>
25# include <QtCore/qobject.h>
26#endif
27
29
30QT_ENABLE_P0846_SEMANTICS_FOR(get_if)
31QT_ENABLE_P0846_SEMANTICS_FOR(get)
32
33class QBitArray;
34class QDataStream;
35class QDate;
36class QDateTime;
37class QEasingCurve;
38class QLine;
39class QLineF;
40class QLocale;
41class QModelIndex;
43class QPoint;
44class QPointF;
45class QRect;
46class QRectF;
48class QSize;
49class QSizeF;
50class QTextFormat;
51class QTextLength;
52class QTime;
53class QTransform;
54class QUrl;
55class QVariant;
56
57template<typename T>
58inline T qvariant_cast(const QVariant &);
59
60namespace QtPrivate {
61template<> constexpr inline bool qIsRelocatable<QVariant> = true;
62}
63class Q_CORE_EXPORT QVariant
64{
65 template <typename T, typename... Args>
66 using if_constructible = std::enable_if_t<
67 std::conjunction_v<
68 std::is_copy_constructible<q20::remove_cvref_t<T>>,
69 std::is_destructible<q20::remove_cvref_t<T>>,
70 std::is_constructible<q20::remove_cvref_t<T>, Args...>
71 >,
72 bool>;
73
74 template <typename T>
75 using if_rvalue = std::enable_if_t<!std::is_reference_v<T>, bool>;
76
77 struct CborValueStandIn { qint64 n; void *c; int t; };
78public:
80 {
81 private:
82 inline PrivateShared() : ref(1) { }
83 public:
84 static int computeOffset(PrivateShared *ps, size_t align);
85 static size_t computeAllocationSize(size_t size, size_t align);
86 static PrivateShared *create(size_t size, size_t align);
87 static void free(PrivateShared *p);
88
89 alignas(8) QAtomicInt ref;
90 int offset;
91
92 const void *data() const { return reinterpret_cast<const uchar *>(this) + offset; }
93 void *data() { return reinterpret_cast<uchar *>(this) + offset; }
94 };
95
96 struct Private
97 {
98 static constexpr size_t MaxInternalSize = 3 * sizeof(void *);
99 template <size_t S> static constexpr bool FitsInInternalSize = S <= MaxInternalSize;
100 template<typename T> static constexpr bool CanUseInternalSpace =
101 (QTypeInfo<T>::isRelocatable && FitsInInternalSize<sizeof(T)> && alignof(T) <= alignof(double));
103 {
104 Q_ASSERT(type);
105 return QMetaType::TypeFlags(type->flags) & QMetaType::RelocatableType &&
106 size_t(type->size) <= MaxInternalSize && size_t(type->alignment) <= alignof(double);
107 }
108
109 union
110 {
111 uchar data[MaxInternalSize] = {};
113 double _forAlignment; // we want an 8byte alignment on 32bit systems as well
117 quintptr packedType : sizeof(QMetaType) * 8 - 2;
118
119 constexpr Private() noexcept : is_shared(false), is_null(true), packedType(0) {}
120 explicit Private(const QtPrivate::QMetaTypeInterface *iface) noexcept;
121 template <typename T> explicit Private(std::piecewise_construct_t, const T &t);
122
123 const void *storage() const
124 { return is_shared ? data.shared->data() : &data.data; }
125
126 // determine internal storage at compile time
127 template<typename T> const T &get() const
128 { return *static_cast<const T *>(CanUseInternalSpace<T> ? &data.data : data.shared->data()); }
129
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 {
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#ifndef QT_NO_GEOM_VARIANT
286 QVariant(QSize size) noexcept;
287 QVariant(QSizeF size) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>);
288 QVariant(QPoint pt) noexcept;
289 QVariant(QPointF pt) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>);
290 QVariant(QLine line) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>);
291 QVariant(QLineF line) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>);
292 QVariant(QRect rect) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>);
293 QVariant(QRectF rect) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>);
294#endif
295
296 // not noexcept
297 QVariant(const QEasingCurve &easing) noexcept(false);
298 QVariant(const QJsonDocument &jsonDocument) noexcept(false);
299 QVariant(const QPersistentModelIndex &modelIndex) noexcept(false);
300
301#ifndef QT_NO_CAST_FROM_ASCII
302 QT_ASCII_CAST_WARN QVariant(const char *str) noexcept(false)
303 : QVariant(QString::fromUtf8(str))
304 {}
305#endif
306 QVariant(QLatin1StringView string) noexcept(false); // converts to QString
307
308#if !defined(Q_CC_GHS)
309 // GHS has an ICE with this code; use the simplified version below
310 template <typename T,
311 std::enable_if_t<std::disjunction_v<std::is_pointer<T>, std::is_member_pointer<T>>, bool> = false>
312 QVariant(T) = delete;
313#else
314 QVariant(const volatile void *) = delete;
315#endif
316
317#if QT_CORE_REMOVED_SINCE(6, 5)
318 QVariant(const QSize &size);
319 QVariant(const QSizeF &size);
320 QVariant(const QPoint &pt);
321 QVariant(const QPointF &pt);
322 QVariant(const QLine &line);
323 QVariant(const QLineF &line);
324 QVariant(const QRect &rect);
325 QVariant(const QRectF &rect);
326 QVariant(const QUuid &uuid);
327#endif
328
329 QVariant& operator=(const QVariant &other);
330 inline QVariant(QVariant &&other) noexcept : d(other.d)
331 { other.d = Private(); }
332 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QVariant)
333
334 inline void swap(QVariant &other) noexcept { std::swap(d, other.d); }
335
336 int userType() const { return typeId(); }
337 int typeId() const { return metaType().id(); }
338
339 const char *typeName() const;
340 QMetaType metaType() const;
341
342 bool canConvert(QMetaType targetType) const
343 { return QMetaType::canConvert(d.type(), targetType); }
344 bool convert(QMetaType type);
345
346 bool canView(QMetaType targetType) const
347 { return QMetaType::canView(d.type(), targetType); }
348
349#if QT_DEPRECATED_SINCE(6, 0)
351 bool canConvert(int targetTypeId) const
352 { return QMetaType::canConvert(d.type(), QMetaType(targetTypeId)); }
354 bool convert(int targetTypeId)
355 { return convert(QMetaType(targetTypeId)); }
356#endif
357
358 inline bool isValid() const;
359 bool isNull() const;
360
361 void clear();
362
363 void detach();
364 inline bool isDetached() const;
365
366 int toInt(bool *ok = nullptr) const;
367 uint toUInt(bool *ok = nullptr) const;
368 qlonglong toLongLong(bool *ok = nullptr) const;
369 qulonglong toULongLong(bool *ok = nullptr) const;
370 bool toBool() const;
371 double toDouble(bool *ok = nullptr) const;
372 float toFloat(bool *ok = nullptr) const;
373 qreal toReal(bool *ok = nullptr) const;
374 QByteArray toByteArray() const;
375 QBitArray toBitArray() const;
376 QString toString() const;
378 QChar toChar() const;
379 QDate toDate() const;
380 QTime toTime() const;
381 QDateTime toDateTime() const;
382 QList<QVariant> toList() const;
384 QHash<QString, QVariant> toHash() const;
385
386#ifndef QT_NO_GEOM_VARIANT
387 QPoint toPoint() const;
388 QPointF toPointF() const;
389 QRect toRect() const;
390 QSize toSize() const;
391 QSizeF toSizeF() const;
392 QLine toLine() const;
393 QLineF toLineF() const;
394 QRectF toRectF() const;
395#endif
396 QLocale toLocale() const;
397#if QT_CONFIG(regularexpression)
398 QRegularExpression toRegularExpression() const;
399#endif // QT_CONFIG(regularexpression)
400#if QT_CONFIG(easingcurve)
401 QEasingCurve toEasingCurve() const;
402#endif
403 QUuid toUuid() const;
404#ifndef QT_BOOTSTRAPPED
405 QUrl toUrl() const;
406 QJsonValue toJsonValue() const;
407 QJsonObject toJsonObject() const;
408 QJsonArray toJsonArray() const;
409 QJsonDocument toJsonDocument() const;
410#endif // QT_BOOTSTRAPPED
411#if QT_CONFIG(itemmodel)
412 QModelIndex toModelIndex() const;
413 QPersistentModelIndex toPersistentModelIndex() const;
414#endif
415
416#ifndef QT_NO_DATASTREAM
417 void load(QDataStream &ds);
418 void save(QDataStream &ds) const;
419#endif
420#if QT_DEPRECATED_SINCE(6, 0)
423 QT_DEPRECATED_VERSION_X_6_0("Use the constructor taking a QMetaType instead.")
425 : QVariant(QMetaType(int(type)))
426 {}
427 QT_DEPRECATED_VERSION_X_6_0("Use typeId() or metaType().")
428 Type type() const
429 {
430 int type = d.type().id();
431 return type >= QMetaType::User ? UserType : static_cast<Type>(type);
432 }
434 static const char *typeToName(int typeId)
435 { return QMetaType(typeId).name(); }
437 static Type nameToType(const char *name)
438 {
439 int metaType = QMetaType::fromName(name).id();
440 return metaType <= int(UserType) ? QVariant::Type(metaType) : UserType;
441 }
443#endif
444
445 void *data();
446 const void *constData() const
447 { return d.storage(); }
448 inline const void *data() const { return constData(); }
449
450private:
451 template <typename T>
452 void verifySuitableForEmplace()
453 {
454 static_assert(!std::is_reference_v<T>,
455 "QVariant does not support reference types");
456 static_assert(!std::is_const_v<T>,
457 "QVariant does not support const types");
458 static_assert(std::is_copy_constructible_v<T>,
459 "QVariant requires that the type is copyable");
460 static_assert(std::is_destructible_v<T>,
461 "QVariant requires that the type is destructible");
462 }
463
464 template <typename T, typename... Args>
465 T &emplaceImpl(Args&&... args)
466 {
467 verifySuitableForEmplace<T>();
468 auto data = static_cast<T *>(prepareForEmplace(QMetaType::fromType<T>()));
469 return *q20::construct_at(data, std::forward<Args>(args)...);
470 }
471
472public:
473 template <typename T, typename... Args,
474 if_constructible<T, Args...> = true>
475 T &emplace(Args&&... args)
476 {
477 return emplaceImpl<T>(std::forward<Args>(args)...);
478 }
479
480 template <typename T, typename U, typename... Args,
481 if_constructible<T, std::initializer_list<U> &, Args...> = true>
482 T &emplace(std::initializer_list<U> list, Args&&... args)
483 {
484 return emplaceImpl<T>(list, std::forward<Args>(args)...);
485 }
486
487 template<typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, QVariant>>>
488 void setValue(T &&avalue)
489 {
490 using VT = std::decay_t<T>;
491 QMetaType metaType = QMetaType::fromType<VT>();
492 // If possible we reuse the current QVariant private.
493 if (isDetached() && d.type() == metaType) {
494 *reinterpret_cast<VT *>(const_cast<void *>(constData())) = std::forward<T>(avalue);
495 } else {
496 *this = QVariant::fromValue<VT>(std::forward<T>(avalue));
497 }
498 }
499
500 void setValue(const QVariant &avalue)
501 {
502 *this = avalue;
503 }
504
505 void setValue(QVariant &&avalue)
506 {
507 *this = std::move(avalue);
508 }
509
510 template<typename T>
511 inline T value() const &
512 { return qvariant_cast<T>(*this); }
513
514 template<typename T>
515 inline T view()
516 {
517 T t{};
518 QMetaType::view(metaType(), data(), QMetaType::fromType<T>(), &t);
519 return t;
520 }
521
522 template<typename T>
523 inline T value() &&
524 { return qvariant_cast<T>(std::move(*this)); }
525
526 template<typename T, if_rvalue<T> = true>
527#ifndef Q_QDOC
528 /* needs is_copy_constructible for variants semantics, is_move_constructible so that moveConstruct works
529 (but copy_constructible implies move_constructble, so don't bother checking)
530 */
531 static inline auto fromValue(T &&value)
532 noexcept(std::is_nothrow_copy_constructible_v<T> && Private::CanUseInternalSpace<T>)
533 -> std::enable_if_t<std::conjunction_v<std::is_copy_constructible<T>,
534 std::is_destructible<T>>, QVariant>
535#else
536 static inline QVariant fromValue(T &&value)
537#endif
538 {
539 // handle special cases
540 using Type = std::remove_cv_t<T>;
541 if constexpr (std::is_null_pointer_v<Type>)
542 return QVariant(QMetaType::fromType<std::nullptr_t>());
543 else if constexpr (std::is_same_v<Type, QVariant>)
544 return std::forward<T>(value);
545 else if constexpr (std::is_same_v<Type, std::monostate>)
546 return QVariant();
547 QMetaType mt = QMetaType::fromType<Type>();
548 mt.registerType(); // we want the type stored in QVariant to always be registered
549 // T is a forwarding reference, so if T satifies the enable-ifery,
550 // we get this overload even if T is an lvalue reference and thus must check here
551 // Moreover, we only try to move if the type is actually moveable and not if T is const
552 // as in const int i; QVariant::fromValue(std::move(i));
553 if constexpr (std::conjunction_v<std::is_move_constructible<Type>, std::negation<std::is_const<T>>>)
554 return moveConstruct(QMetaType::fromType<Type>(), std::addressof(value));
555 else
556 return copyConstruct(mt, std::addressof(value));
557 }
558
559 template<typename T>
560#ifndef Q_QDOC
561 static inline auto fromValue(const T &value)
562 noexcept(std::is_nothrow_copy_constructible_v<T> && Private::CanUseInternalSpace<T>)
563 -> std::enable_if_t<std::is_copy_constructible_v<T> && std::is_destructible_v<T>, QVariant>
564#else
565 static inline QVariant fromValue(const T &value)
566#endif
567 {
568 if constexpr (std::is_null_pointer_v<T>)
569 return QVariant(QMetaType::fromType<std::nullptr_t>());
570 else if constexpr (std::is_same_v<T, QVariant>)
571 return value;
572 else if constexpr (std::is_same_v<T, std::monostate>)
573 return QVariant();
574 return QVariant(QMetaType::fromType<T>(), std::addressof(value));
575 }
576
577 template<typename... Types>
578 static inline QVariant fromStdVariant(const std::variant<Types...> &value)
579 {
580 return fromStdVariantImpl(value);
581 }
582
583 template<typename... Types>
584 static QVariant fromStdVariant(std::variant<Types...> &&value)
585 {
586 return fromStdVariantImpl(std::move(value));
587 }
588
589 template<typename T>
590 bool canConvert() const
591 { return canConvert(QMetaType::fromType<T>()); }
592
593 template<typename T>
594 bool canView() const
595 { return canView(QMetaType::fromType<T>()); }
596
597 static QPartialOrdering compare(const QVariant &lhs, const QVariant &rhs);
598
599private:
600 template <typename StdVariant>
601 static QVariant fromStdVariantImpl(StdVariant &&v)
602 {
603 if (Q_UNLIKELY(v.valueless_by_exception()))
604 return QVariant();
605 auto visitor = [](auto &&arg) {
606 return QVariant::fromValue(q23::forward_like<StdVariant>(arg));
607 };
608 return std::visit(visitor, std::forward<StdVariant>(v));
609 }
610
611 friend inline bool operator==(const QVariant &a, const QVariant &b)
612 { return a.equals(b); }
613 friend inline bool operator!=(const QVariant &a, const QVariant &b)
614 { return !a.equals(b); }
615#ifndef QT_NO_DEBUG_STREAM
616 template <typename T>
617 friend auto operator<<(const QDebug &debug, const T &variant) -> std::enable_if_t<std::is_same_v<T, QVariant>, QDebug> {
618 return variant.qdebugHelper(debug);
619 }
620 QDebug qdebugHelper(QDebug) const;
621#endif
622
623 template <typename T>
624 friend T *get_if(QVariant *v) noexcept
625 {
626 // data() will detach from is_null, returning non-nullptr
627 if (!v || v->d.type() != QMetaType::fromType<T>())
628 return nullptr;
629 return static_cast<T*>(v->data());
630 }
631 template <typename T>
632 friend const T *get_if(const QVariant *v) noexcept
633 {
634 // (const) data() will not detach from is_null, return nullptr
635 if (!v || v->d.is_null || v->d.type() != QMetaType::fromType<T>())
636 return nullptr;
637 return static_cast<const T*>(v->data());
638 }
639
640#define Q_MK_GET(cvref) \
641 template <typename T> \
642 friend T cvref get(QVariant cvref v) \
643 { \
644 if constexpr (std::is_const_v<T cvref>) \
645 Q_ASSERT(!v.d.is_null); \
646 Q_ASSERT(v.d.type() == QMetaType::fromType<q20::remove_cvref_t<T>>()); \
647 return static_cast<T cvref>(*get_if<T>(&v)); \
648 } \
649 /* end */
650 Q_MK_GET(&)
651 Q_MK_GET(const &)
652 Q_MK_GET(&&)
653 Q_MK_GET(const &&)
654#undef Q_MK_GET
655
656 static QVariant moveConstruct(QMetaType type, void *data);
657 static QVariant copyConstruct(QMetaType type, const void *data);
658
659 template<typename T>
660 friend inline T qvariant_cast(const QVariant &);
661 template<typename T>
662 friend inline T qvariant_cast(QVariant &&);
663
664protected:
666 void create(int type, const void *copy);
667 void create(QMetaType type, const void *copy);
668 bool equals(const QVariant &other) const;
669 bool convert(int type, void *ptr) const;
670 bool view(int type, void *ptr);
671
672private:
673 // force compile error, prevent QVariant(bool) to be called
674 inline QVariant(void *) = delete;
675 // QVariant::Type is marked as \obsolete, but we don't want to
676 // provide a constructor from its intended replacement,
677 // QMetaType::Type, instead, because the idea behind these
678 // constructors is flawed in the first place. But we also don't
679 // want QVariant(QMetaType::String) to compile and falsely be an
680 // int variant, so delete this constructor:
681 QVariant(QMetaType::Type) = delete;
682
683 // used to setup the QVariant internals for the "real" inplace ctor
684 QVariant(std::in_place_t, QMetaType type);
685 // helper for emplace
686 void *prepareForEmplace(QMetaType type);
687
688 // These constructors don't create QVariants of the type associated
689 // with the enum, as expected, but they would create a QVariant of
690 // type int with the value of the enum value.
691 // Use QVariant v = QColor(Qt::red) instead of QVariant v = Qt::red for
692 // example.
693 QVariant(Qt::GlobalColor) = delete;
694 QVariant(Qt::BrushStyle) = delete;
695 QVariant(Qt::PenStyle) = delete;
696 QVariant(Qt::CursorShape) = delete;
697#ifdef QT_NO_CAST_FROM_ASCII
698 // force compile error when implicit conversion is not wanted
699 inline QVariant(const char *) = delete;
700#endif
701public:
703 inline DataPtr &data_ptr() { return d; }
704 inline const DataPtr &data_ptr() const { return d; }
705};
706
707inline bool QVariant::isValid() const
708{
709 return d.type().isValid();
710}
711
712#ifndef QT_NO_DATASTREAM
714Q_CORE_EXPORT QDataStream &operator<<(QDataStream &s, const QVariant &p);
715
716#if QT_DEPRECATED_SINCE(6, 0)
720inline QDataStream &operator>>(QDataStream &s, QVariant::Type &p)
721{
722 quint32 u;
723 s >> u;
724 p = static_cast<QVariant::Type>(u);
725 return s;
726}
728inline QDataStream &operator<<(QDataStream &s, const QVariant::Type p)
729{
730 s << static_cast<quint32>(p);
731 return s;
732}
734#endif
735
736#endif
737
738inline bool QVariant::isDetached() const
739{ return !d.is_shared || d.data.shared->ref.loadRelaxed() == 1; }
740
741inline void swap(QVariant &value1, QVariant &value2) noexcept
742{ value1.swap(value2); }
743
744#ifndef QT_MOC
745
746template<typename T> inline T qvariant_cast(const QVariant &v)
747{
748 QMetaType targetType = QMetaType::fromType<T>();
749 if (v.d.type() == targetType)
750 return v.d.get<T>();
751 if constexpr (std::is_same_v<T,std::remove_const_t<std::remove_pointer_t<T>> const *>) {
752 using nonConstT = std::remove_const_t<std::remove_pointer_t<T>> *;
753 QMetaType nonConstTargetType = QMetaType::fromType<nonConstT>();
754 if (v.d.type() == nonConstTargetType)
755 return v.d.get<nonConstT>();
756 }
757
758 T t{};
759 QMetaType::convert(v.metaType(), v.constData(), targetType, &t);
760 return t;
761}
762
763template<typename T> inline T qvariant_cast(QVariant &&v)
764{
765 QMetaType targetType = QMetaType::fromType<T>();
766 if (v.d.type() == targetType) {
767 if constexpr (QVariant::Private::CanUseInternalSpace<T>) {
768 return std::move(*reinterpret_cast<T *>(v.d.data.data));
769 } else {
770 if (v.d.data.shared->ref.loadRelaxed() == 1)
771 return std::move(*reinterpret_cast<T *>(v.d.data.shared->data()));
772 else
773 return v.d.get<T>();
774 }
775 }
776 if constexpr (std::is_same_v<T, QVariant>) {
777 // if the metatype doesn't match, but we want a QVariant, just return the current variant
778 return v;
779 } if constexpr (std::is_same_v<T,std::remove_const_t<std::remove_pointer_t<T>> const *>) {
780 // moving a pointer is pointless, just do the same as the const & overload
781 using nonConstT = std::remove_const_t<std::remove_pointer_t<T>> *;
782 QMetaType nonConstTargetType = QMetaType::fromType<nonConstT>();
783 if (v.d.type() == nonConstTargetType)
784 return v.d.get<nonConstT>();
785 }
786
787 T t{};
788 QMetaType::convert(v.metaType(), v.constData(), targetType, &t);
789 return t;
790}
791
793{
794 if (v.metaType().id() == QMetaType::QVariant)
795 return *reinterpret_cast<const QVariant *>(v.constData());
796 return v;
797}
798
799#endif
800
801#ifndef QT_NO_DEBUG_STREAM
802#if QT_DEPRECATED_SINCE(6, 0)
806Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type);
808#endif
809#endif
810
811namespace QtPrivate {
812class Q_CORE_EXPORT QVariantTypeCoercer
813{
814public:
815 // ### Qt7: Pass QMetaType as value rather than const ref.
816 const void *convert(const QVariant &value, const QMetaType &type);
817 const void *coerce(const QVariant &value, const QMetaType &type);
818
819private:
820 QVariant converted;
821};
822}
823
824template<typename Pointer>
826{
827private:
828 const Pointer *m_pointer = nullptr;
829
830public:
831 explicit QVariantRef(const Pointer *reference) : m_pointer(reference) {}
832 QVariantRef(const QVariantRef &) = default;
834 ~QVariantRef() = default;
835
836 operator QVariant() const;
840
842 {
843 QVariant tmp = a;
844 a = b;
845 b = std::move(tmp);
846 }
847};
848
849class Q_CORE_EXPORT QVariantConstPointer
850{
851private:
852 QVariant m_variant;
853
854public:
856
857 QVariant operator*() const;
858 const QVariant *operator->() const;
859};
860
861template<typename Pointer>
863{
864private:
865 const Pointer *m_pointer = nullptr;
866
867public:
868 explicit QVariantPointer(const Pointer *pointer) : m_pointer(pointer) {}
870 Pointer operator->() const { return *m_pointer; }
871};
872
874
875#endif // QVARIANT_H
\inmodule QtCore
Definition qatomic.h:112
\inmodule QtCore
Definition qbitarray.h:13
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
Definition qchar.h:48
\inmodule QtCore\reentrant
Definition qdatastream.h:30
\inmodule QtCore\reentrant
Definition qdatetime.h:257
\inmodule QtCore \reentrant
Definition qdatetime.h:27
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore
Definition qhash.h:818
\inmodule QtCore\reentrant
Definition qjsonarray.h:18
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
Definition qjsonobject.h:20
\inmodule QtCore\reentrant
Definition qjsonvalue.h:24
\inmodule QtCore
Definition qline.h:182
\inmodule QtCore
Definition qline.h:18
Definition qmap.h:186
\inmodule QtCore
Definition qmetatype.h:320
static bool canConvert(QMetaType fromType, QMetaType toType)
Returns true if QMetaType::convert can convert from fromType to toType.
static bool canView(QMetaType fromType, QMetaType toType)
Returns true if QMetaType::view can create a mutable view of type toType on type fromType.
static bool view(QMetaType fromType, void *from, QMetaType toType, void *to)
Creates a mutable view on the object at from of fromType in the preallocated space at to typed toType...
static QMetaType fromName(QByteArrayView name)
Returns a QMetaType matching typeName.
bool isValid() const
int id(int=0) const
Definition qmetatype.h:454
@ RelocatableType
Definition qmetatype.h:381
Type
\macro Q_DECLARE_OPAQUE_POINTER(PointerType)
Definition qmetatype.h:324
void registerType() const
Definition qmetatype.h:444
constexpr const char * name() const
Definition qmetatype.h:2650
static bool convert(QMetaType fromType, const void *from, QMetaType toType, void *to)
Converts the object at from from fromType to the preallocated space at to typed toType.
friend class QVariant
Definition qmetatype.h:775
\inmodule QtCore
\inmodule QtCore\reentrant
Definition qpoint.h:214
\inmodule QtCore\reentrant
Definition qpoint.h:23
\inmodule QtCore\reentrant
Definition qrect.h:483
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore \reentrant
\inmodule QtCore
Definition qsize.h:207
\inmodule QtCore
Definition qsize.h:25
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
\reentrant
Definition qtextformat.h:90
\reentrant
Definition qtextformat.h:45
\inmodule QtCore \reentrant
Definition qdatetime.h:189
The QTransform class specifies 2D transformations of a coordinate system.
Definition qtransform.h:20
\inmodule QtCore
Definition qurl.h:94
\inmodule QtCore
Definition quuid.h:31
Emulated const pointer to QVariant based on a pointer.
Definition qvariant.h:850
QVariantPointer is a template class that emulates a pointer to QVariant based on a pointer.
Definition qvariant.h:863
QVariantPointer(const Pointer *pointer)
Constructs a QVariantPointer from the given pointer.
Definition qvariant.h:868
Pointer operator->() const
Dereferences and returns the pointer.
Definition qvariant.h:870
QVariantRef< Pointer > operator*() const
Dereferences the QVariantPointer to a QVariantRef.
Definition qvariant.h:869
The QVariantRef acts as a non-const reference to a QVariant.
Definition qvariant.h:826
QVariantRef(const Pointer *reference)
Creates a QVariantRef from an pointer.
Definition qvariant.h:831
~QVariantRef()=default
QVariantRef & operator=(const QVariantRef &value)
Assigns a new value to the value pointed to by the pointer this QVariantRef refers to.
Definition qvariant.h:838
QVariantRef(const QVariantRef &)=default
QVariantRef & operator=(QVariantRef &&value)
Assigns a new value to the value pointed to by the pointer this QVariantRef refers to.
Definition qvariant.h:839
QVariantRef(QVariantRef &&)=default
friend void swap(QVariantRef a, QVariantRef b)
Definition qvariant.h:841
QVariantRef & operator=(const QVariant &value)
Assigns a new value to the value pointed to by the pointer this QVariantRef refers to.
\inmodule QtCore
Definition qvariant.h:64
bool canView(QMetaType targetType) const
Definition qvariant.h:346
friend const T * get_if(const QVariant *v) noexcept
Definition qvariant.h:632
DataPtr & data_ptr()
Definition qvariant.h:703
T & emplace(Args &&... args)
Definition qvariant.h:475
QVariant(const QPersistentModelIndex &modelIndex) noexcept(false)
const void * data() const
Returns a pointer to the contained object as a generic void* that cannot be written to.
Definition qvariant.h:448
bool canConvert() const
Returns true if the variant can be converted to the template type {T}, otherwise false.
Definition qvariant.h:590
T value() const &
Definition qvariant.h:511
QVariant() noexcept
Constructs an invalid variant.
Definition qvariant.h:217
QVariant(std::in_place_type_t< T >, Args &&... args) noexcept(is_noexcept_constructible< q20::remove_cvref_t< T >, Args... >::value)
Definition qvariant.h:232
T view()
Returns a mutable view of template type {T} on the stored value.
Definition qvariant.h:515
bool isDetached() const
Definition qvariant.h:738
T & emplace(std::initializer_list< U > list, Args &&... args)
Definition qvariant.h:482
QVariant(const QRegularExpression &re) noexcept
QVariant(QVariant &&other) noexcept
Move-constructs a QVariant instance, making it point at the same object that other was pointing to.
Definition qvariant.h:330
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:707
friend bool operator==(const QVariant &a, const QVariant &b)
Returns true if v1 and v2 are equal; otherwise returns false.
Definition qvariant.h:611
bool canView() const
Returns true if a mutable view of the template type {T} can be created on this variant,...
Definition qvariant.h:594
const DataPtr & data_ptr() const
Definition qvariant.h:704
static QVariant fromStdVariant(const std::variant< Types... > &value)
Definition qvariant.h:578
friend bool operator!=(const QVariant &a, const QVariant &b)
Returns false if v1 and v2 are equal; otherwise returns true.
Definition qvariant.h:613
int userType() const
Definition qvariant.h:336
friend T * get_if(QVariant *v) noexcept
If v contains an object of type T, returns a pointer to the contained object, otherwise returns \null...
Definition qvariant.h:624
QT_ASCII_CAST_WARN QVariant(const char *str) noexcept(false)
Constructs a new variant with a string value of val.
Definition qvariant.h:302
QVariant(const QModelIndex &modelIndex) noexcept(Private::FitsInInternalSize< 8+2 *sizeof(quintptr)>)
static auto fromValue(const T &value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::is_copy_constructible_v< T > &&std::is_destructible_v< T >, QVariant >
Returns a QVariant containing a copy of value.
Definition qvariant.h:561
void setValue(const QVariant &avalue)
Copies value over this QVariant.
Definition qvariant.h:500
void setValue(QVariant &&avalue)
Moves value over this QVariant.
Definition qvariant.h:505
friend auto operator<<(const QDebug &debug, const T &variant) -> std::enable_if_t< std::is_same_v< T, QVariant >, QDebug >
Definition qvariant.h:617
int typeId() const
Returns the storage type of the value stored in the variant.
Definition qvariant.h:337
static QVariant fromStdVariant(std::variant< Types... > &&value)
Definition qvariant.h:584
bool canConvert(QMetaType targetType) const
Definition qvariant.h:342
Private DataPtr
Definition qvariant.h:702
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:531
Private d
Definition qvariant.h:665
QVariant(std::in_place_type_t< T >, std::initializer_list< U > il, Args &&... args) noexcept(is_noexcept_constructible< q20::remove_cvref_t< T >, std::initializer_list< U > &, Args... >::value)
Definition qvariant.h:242
T value() &&
Definition qvariant.h:523
QVariant(const QEasingCurve &easing) noexcept(false)
QVariant(T)=delete
void setValue(T &&avalue)
Stores a copy of value.
Definition qvariant.h:488
const void * constData() const
Definition qvariant.h:446
QHash< int, QWidget * > hash
[35multi]
QString str
[2]
QMap< QString, QString > map
[6]
b clear()
p1 load("image.bmp")
QDate date
[1]
rect
[4]
Combined button and popup list for selecting options.
\macro QT_NAMESPACE
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION ParsedNumber< float > toFloat(QByteArrayView a) noexcept
constexpr bool qIsRelocatable< QVariant >
Definition qvariant.h:61
bool isNull(const T &t)
CursorShape
GlobalColor
Definition qnamespace.h:26
BrushStyle
T * construct_at(T *ptr, Args &&... args)
Definition q20memory.h:41
void toByteArray(QByteArray &)
Definition qctf_p.h:78
static jboolean copy(JNIEnv *, jobject)
#define Q_UNLIKELY(x)
#define QT_WARNING_POP
#define QT_WARNING_DISABLE_DEPRECATED
#define QT_WARNING_PUSH
constexpr timespec operator*(const timespec &t1, int mul)
static QDBusError::ErrorType get(const char *name)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
void uint64_t uint64_t uint64_t value2
#define Size(name)
static ControlElement< T > * ptr(QWidget *widget)
@ Invalid
const char * typeName
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLfloat GLfloat f
GLint reference
GLenum type
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLint ref
GLuint name
GLfloat n
const GLubyte * c
GLdouble GLdouble t
Definition qopenglext.h:243
GLsizei const void * pointer
Definition qopenglext.h:384
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
XID Pixmap
static constexpr To convert(const std::array< Mapping, N > &mapping, From Mapping::*from, To Mapping::*to, From value, To defaultValue)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static ISC_DATE toDate(QDate t)
static QList< QVariant > toList(char **buf, int count)
static ISC_TIME toTime(QTime t)
SSL_CTX int(*) void arg)
#define QT_ASCII_CAST_WARN
#define QT_DEPRECATED_VERSION_X_6_0(text)
#define QT_DEPRECATED_VERSION_6_0
char Char
static QStringList toStringList(const QJsonArray &jsonArray)
static int compare(quint64 a, quint64 b)
unsigned int quint32
Definition qtypes.h:45
unsigned char uchar
Definition qtypes.h:27
size_t quintptr
Definition qtypes.h:72
quint64 qulonglong
Definition qtypes.h:59
unsigned int uint
Definition qtypes.h:29
long long qint64
Definition qtypes.h:55
double qreal
Definition qtypes.h:92
qint64 qlonglong
Definition qtypes.h:58
static int toInt(const QChar &qc, int R)
static double toDouble(Value v)
Q_CORE_EXPORT QDataStream & operator>>(QDataStream &s, QVariant &p)
#define Q_MK_GET(cvref)
Definition qvariant.h:640
QVariant qvariant_cast< QVariant >(const QVariant &v)
Definition qvariant.h:792
Q_CORE_EXPORT QDataStream & operator<<(QDataStream &s, const QVariant &p)
T qvariant_cast(const QVariant &)
Definition qvariant.h:746
#define explicit
QList< int > list
[14]
QByteArray bytearray
[3]
QUrl url("example.com")
[constructor-url-reference]
QVariant variant
[1]
value toMap().value(key)
[3]
QEasingCurve easing(QEasingCurve::InOutQuad)
[typedef]
QSharedPointer< T > other(t)
[5]
this swap(other)
QQuickView * view
[0]
view create()
char * toString(const MyType &t)
[31]
QJSValueList args
Definition parser.h:19
const void * data() const
Definition qvariant.h:92
static constexpr bool canUseInternalSpace(const QtPrivate::QMetaTypeInterface *type)
Definition qvariant.h:102
PrivateShared * shared
Definition qvariant.h:112
const void * storage() const
Definition qvariant.h:123
quintptr is_shared
Definition qvariant.h:115
const T & get() const
Definition qvariant.h:127
quintptr packedType
Definition qvariant.h:117
const QtPrivate::QMetaTypeInterface * typeInterface() const
Definition qvariant.h:130
quintptr is_null
Definition qvariant.h:116
uchar data[MaxInternalSize]
Definition qvariant.h:111
constexpr Private() noexcept
Definition qvariant.h:119
double _forAlignment
Definition qvariant.h:113
QMetaType type() const
Definition qvariant.h:135
Definition moc.h:24
QT_BEGIN_NAMESPACE bool toBool(const QString &str)
Definition utils.h:14