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// Qt-Security score:critical reason:data-parser
4
5#ifndef QVARIANT_H
6#define QVARIANT_H
7
8#include <QtCore/qatomic.h>
9#include <QtCore/qcompare.h>
10#include <QtCore/qcontainerfwd.h>
11#include <QtCore/qmetatype.h>
12#ifndef QT_NO_DEBUG_STREAM
13#include <QtCore/qdebug.h>
14#endif
15
16#include <memory>
17#include <QtCore/q20type_traits.h>
18#include <QtCore/q23utility.h>
19#include <variant>
20
21#if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 1
22# include <QtCore/qlist.h>
23# include <QtCore/qstringlist.h>
24# include <QtCore/qbytearraylist.h>
25# include <QtCore/qhash.h>
26# include <QtCore/qmap.h>
27# include <QtCore/qobject.h>
28#endif
29
30QT_BEGIN_NAMESPACE
31
32QT_ENABLE_P0846_SEMANTICS_FOR(get_if)
33QT_ENABLE_P0846_SEMANTICS_FOR(get)
34
35class QBitArray;
36class QDataStream;
37class QDate;
38class QDateTime;
39class QEasingCurve;
40class QLine;
41class QLineF;
42class QLocale;
43class QModelIndex;
44class QPersistentModelIndex;
45class QPoint;
46class QPointF;
47class QRect;
48class QRectF;
49class QRegularExpression;
50class QSize;
51class QSizeF;
52class QTextFormat;
53class QTextLength;
54class QTime;
55class QTransform;
56class QUrl;
57class QVariant;
58
59template<typename T>
60inline T qvariant_cast(const QVariant &);
61
62namespace QtPrivate {
63template<> constexpr inline bool qIsRelocatable<QVariant> = true;
64
65} // namespace QtPrivate
66
67class Q_CORE_EXPORT QVariant
68{
69 template <typename T, typename... Args>
70 using if_constructible = std::enable_if_t<
71 std::conjunction_v<
72 std::is_copy_constructible<q20::remove_cvref_t<T>>,
73 std::is_destructible<q20::remove_cvref_t<T>>,
74 std::is_constructible<q20::remove_cvref_t<T>, Args...>
75 >,
76 bool>;
77
78 template <typename T>
79 using if_rvalue = std::enable_if_t<!std::is_reference_v<T>, bool>;
80
81 struct CborValueStandIn { qint64 n; void *c; int t; };
82public:
83 struct PrivateShared
84 {
85 private:
86 inline PrivateShared() : ref(1) { }
87 public:
88 static int computeOffset(PrivateShared *ps, size_t align);
89 static size_t computeAllocationSize(size_t size, size_t align);
90 static PrivateShared *create(size_t size, size_t align);
91 static void free(PrivateShared *p);
92
93 alignas(8) QAtomicInt ref;
94 int offset;
95
96 const void *data() const { return reinterpret_cast<const uchar *>(this) + offset; }
97 void *data() { return reinterpret_cast<uchar *>(this) + offset; }
98 };
99
100 struct Private
101 {
102 static constexpr size_t MaxInternalSize = 3 * sizeof(void *);
103 template <size_t S> static constexpr bool FitsInInternalSize = S <= MaxInternalSize;
104 template<typename T> static constexpr bool CanUseInternalSpace =
105 (QTypeInfo<T>::isRelocatable && FitsInInternalSize<sizeof(T)> && alignof(T) <= alignof(double));
106 static constexpr bool canUseInternalSpace(const QtPrivate::QMetaTypeInterface *type)
107 {
108 Q_ASSERT(type);
109 return QMetaType::TypeFlags(type->flags) & QMetaType::RelocatableType &&
110 size_t(type->size) <= MaxInternalSize && size_t(type->alignment) <= alignof(double);
111 }
112
113 template <typename T> static constexpr bool hasAlwaysBeenAbleToUseInternalSpace()
114 {
115 if constexpr (!CanUseInternalSpace<T>)
116 return false;
117#if defined(QT_BOOTSTRAPPED) || defined(QT_STATIC)
118 return true;
119#else
120 // Because it's possible to mark a type relocatable in a later,
121 // dynamic build of Qt, we need to explicitly list which types have
122 // always been relocatable since they were added. Since this is an
123 // optimization, we don't have to be exhaustive.
124 if constexpr (std::is_scalar_v<T>)
125 return true; // scalars are and have always been relocatable
126 if constexpr (QtPrivate::IsQFlags<T>::value)
127 return true; // likewise
128 if constexpr (QtPrivate::qIsQtRelocatableContainer<T>)
129 return true;
130 if constexpr (QMetaTypeId2<T>::IsBuiltIn) {
131 // at release time
132# if QT_VERSION_MAJOR < 7
133 constexpr int LastCoreType = QMetaType::QVariantPair;
134 constexpr int LastGuiType = QMetaType::QColorSpace;
135 constexpr int LastWidgetType = QMetaType::QSizePolicy;
136# else
137 // add at release time
138# endif
139 constexpr int Id = QMetaTypeId2<T>::MetaType;
140 if constexpr (Id <= LastCoreType)
141 return true; // includes QString, QByteArray, etc.
142 if constexpr (Id >= QMetaType::FirstGuiType && Id <= LastGuiType)
143 return true;
144 if constexpr (Id >= QMetaType::FirstWidgetsType && Id <= LastWidgetType)
145 return true;
146 }
147 return false;
148#endif // QT_BOOTSTRAPPED || QT_STATIC
149 }
150
151 union
152 {
153 uchar data[MaxInternalSize] = {};
154 PrivateShared *shared;
155 double _forAlignment; // we want an 8byte alignment on 32bit systems as well
156 } data;
157 quintptr is_shared : 1;
158 quintptr is_null : 1;
159 quintptr packedType : sizeof(QMetaType) * 8 - 2;
160
161 constexpr Private() noexcept : is_shared(false), is_null(true), packedType(0) {}
162 explicit Private(const QtPrivate::QMetaTypeInterface *iface) noexcept;
163 template <typename T>
164 explicit Private(std::in_place_t, T &&t);
165#if QT_DEPRECATED_SINCE(6, 12)
166 template <typename T>
167 QT_DEPRECATED_VERSION_X_6_12("use the std::in_place overload and check whether you can move into it.")
168 explicit Private(std::piecewise_construct_t, const T &t)
169 : Private{std::in_place, t} {}
170#endif
171
172 const void *storage() const
173 { return is_shared ? data.shared->data() : &data.data; }
174
175 template<typename T> const T &get() const
176 {
177 if constexpr (!FitsInInternalSize<sizeof(T)> || alignof(T) > alignof(double)) {
178 // regardless of whether it's marked relocatable now or in the future
179 Q_ASSERT(is_shared);
180 return *static_cast<const T *>(data.shared->data());
181 } else if constexpr (hasAlwaysBeenAbleToUseInternalSpace<T>()) {
182 Q_ASSERT(!is_shared);
183 return *reinterpret_cast<const T *>(data.data);
184 } else {
185 return *static_cast<const T *>(storage());
186 }
187 }
188
189 inline const QtPrivate::QMetaTypeInterface *typeInterface() const
190 {
191 return reinterpret_cast<const QtPrivate::QMetaTypeInterface *>(packedType << 2);
192 }
193
194 inline QMetaType type() const
195 {
196 return QMetaType(typeInterface());
197 }
198 };
199
200#if QT_DEPRECATED_SINCE(6, 0)
201 enum QT_DEPRECATED_VERSION_X_6_0("Use QMetaType::Type instead.") Type
202 {
203 Invalid = QMetaType::UnknownType,
204 Bool = QMetaType::Bool,
205 Int = QMetaType::Int,
206 UInt = QMetaType::UInt,
207 LongLong = QMetaType::LongLong,
208 ULongLong = QMetaType::ULongLong,
209 Double = QMetaType::Double,
210 Char = QMetaType::QChar,
211 Map = QMetaType::QVariantMap,
212 List = QMetaType::QVariantList,
213 String = QMetaType::QString,
214 StringList = QMetaType::QStringList,
215 ByteArray = QMetaType::QByteArray,
216 BitArray = QMetaType::QBitArray,
217 Date = QMetaType::QDate,
218 Time = QMetaType::QTime,
219 DateTime = QMetaType::QDateTime,
220 Url = QMetaType::QUrl,
221 Locale = QMetaType::QLocale,
222 Rect = QMetaType::QRect,
223 RectF = QMetaType::QRectF,
224 Size = QMetaType::QSize,
225 SizeF = QMetaType::QSizeF,
226 Line = QMetaType::QLine,
227 LineF = QMetaType::QLineF,
228 Point = QMetaType::QPoint,
229 PointF = QMetaType::QPointF,
230#if QT_CONFIG(regularexpression)
231 RegularExpression = QMetaType::QRegularExpression,
232#endif
233 Hash = QMetaType::QVariantHash,
234#if QT_CONFIG(easingcurve)
235 EasingCurve = QMetaType::QEasingCurve,
236#endif
237 Uuid = QMetaType::QUuid,
238#if QT_CONFIG(itemmodel)
239 ModelIndex = QMetaType::QModelIndex,
240 PersistentModelIndex = QMetaType::QPersistentModelIndex,
241#endif
242 LastCoreType = QMetaType::LastCoreType,
243
244 Font = QMetaType::QFont,
245 Pixmap = QMetaType::QPixmap,
246 Brush = QMetaType::QBrush,
247 Color = QMetaType::QColor,
248 Palette = QMetaType::QPalette,
249 Image = QMetaType::QImage,
250 Polygon = QMetaType::QPolygon,
251 Region = QMetaType::QRegion,
252 Bitmap = QMetaType::QBitmap,
253 Cursor = QMetaType::QCursor,
254#if QT_CONFIG(shortcut)
255 KeySequence = QMetaType::QKeySequence,
256#endif
257 Pen = QMetaType::QPen,
258 TextLength = QMetaType::QTextLength,
259 TextFormat = QMetaType::QTextFormat,
260 Transform = QMetaType::QTransform,
261 Matrix4x4 = QMetaType::QMatrix4x4,
262 Vector2D = QMetaType::QVector2D,
263 Vector3D = QMetaType::QVector3D,
264 Vector4D = QMetaType::QVector4D,
265 Quaternion = QMetaType::QQuaternion,
266 PolygonF = QMetaType::QPolygonF,
267 Icon = QMetaType::QIcon,
268 LastGuiType = QMetaType::LastGuiType,
269
270 SizePolicy = QMetaType::QSizePolicy,
271
272 UserType = QMetaType::User,
273 LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type
274 };
275#endif
276 QVariant() noexcept : d() {}
277 ~QVariant();
278 explicit QVariant(QMetaType type, const void *copy = nullptr);
279 QVariant(const QVariant &other);
280
281private:
282 template <typename T, typename ...Args>
283 using is_noexcept_constructible = std::conjunction<
284 std::bool_constant<Private::CanUseInternalSpace<T>>,
285 std::is_nothrow_constructible<T, Args...>
286 >;
287
288public:
289 template<typename Indirect>
290 class Reference;
291
292 template<typename Indirect>
293 class ConstReference
294 {
295 private:
296 friend class Reference<Indirect>;
297 const Indirect m_referred;
298
299 public:
300 // You can initialize a const reference from another one, but you can't assign to it.
301
302 explicit ConstReference(const Indirect &referred)
303 noexcept(std::is_nothrow_copy_constructible_v<Indirect>)
304 : m_referred(referred) {}
305 explicit ConstReference(Indirect &&referred)
306 noexcept(std::is_nothrow_move_constructible_v<Indirect>)
307 : m_referred(std::move(referred)) {}
308 ConstReference(const ConstReference &)
309 noexcept(std::is_nothrow_copy_constructible_v<Indirect>) = default;
310
311 // Move-constructing a reference from another one is not valid C++. You can't do this:
312 // A a;
313 // const A &ra(a);
314 // const A &rb(std::move(ra));
315 ConstReference(ConstReference &&) = delete;
316
317 ConstReference(const Reference<Indirect> &)
318 noexcept(std::is_nothrow_copy_constructible_v<Indirect>);
319
320 // Move-constructing a reference from another one is not valid C++. You can't do this:
321 // A a;
322 // A &ra(a);
323 // const A &rb(std::move(ra));
324 // ConstReference(Reference<Indirect> &&) = delete;
325
326 ~ConstReference() = default;
327 ConstReference &operator=(const ConstReference &value) = delete;
328 ConstReference &operator=(ConstReference &&value) = delete;
329
330 // To be specialized for each Indirect
331 operator QVariant() const noexcept(Indirect::CanNoexceptConvertToQVariant);
332 };
333
334 template<typename Indirect>
335 class Reference
336 {
337 private:
338 friend class ConstReference<Indirect>;
339 Indirect m_referred;
340
341 friend void swap(Reference a, Reference b) { return a.swap(b); }
342
343 public:
344 // Assigning and initializing are different operations for references.
345
346 explicit Reference(const Indirect &referred)
347 noexcept(std::is_nothrow_copy_constructible_v<Indirect>)
348 : m_referred(referred) {}
349 explicit Reference(Indirect &&referred)
350 noexcept(std::is_nothrow_move_constructible_v<Indirect>)
351 : m_referred(std::move(referred)) {}
352 Reference(const Reference &) = default;
353
354 // Move-constructing a reference from another one is not valid C++. You can't do this:
355 // A a;
356 // A &ra(a);
357 // A &rb(std::move(ra));
358 Reference(Reference &&) = delete;
359
360 ~Reference() = default;
361
362 Reference &operator=(const Reference &value)
363 noexcept(Indirect::CanNoexceptAssignQVariant)
364 {
365 return operator=(QVariant(value));
366 }
367
368 Reference &operator=(Reference &&value)
369 noexcept(Indirect::CanNoexceptAssignQVariant)
370 {
371 return operator=(QVariant(value));
372 }
373
374 Reference &operator=(const ConstReference<Indirect> &value)
375 noexcept(Indirect::CanNoexceptAssignQVariant)
376 {
377 return operator=(QVariant(value));
378 }
379
380 Reference &operator=(ConstReference<Indirect> &&value)
381 noexcept(Indirect::CanNoexceptAssignQVariant)
382 {
383 return operator=(QVariant(value));
384 }
385
386 operator QVariant() const noexcept(Indirect::CanNoexceptConvertToQVariant)
387 {
388 return ConstReference<Indirect>(m_referred);
389 }
390
391 void swap(Reference b)
392 {
393 // swapping a reference is not swapping the referred item, but swapping its contents.
394 QVariant tmp = *this;
395 *this = std::move(b);
396 b = std::move(tmp);
397 }
398
399 // To be specialized for each Indirect
400 Reference &operator=(const QVariant &value) noexcept(Indirect::CanNoexceptAssignQVariant);
401 };
402
403 template<typename Indirect>
404 class ConstPointer
405 {
406 private:
407 Indirect m_pointed;
408
409 public:
410 explicit ConstPointer(const Indirect &pointed)
411 noexcept(std::is_nothrow_copy_constructible_v<Indirect>)
412 : m_pointed(pointed) {}
413 explicit ConstPointer(Indirect &&pointed)
414 noexcept(std::is_nothrow_move_constructible_v<Indirect>)
415 : m_pointed(std::move(pointed)) {}
416
417 ConstReference<Indirect> operator*()
418 const noexcept(std::is_nothrow_copy_constructible_v<Indirect>)
419 {
420 return ConstReference<Indirect>(m_pointed);
421 }
422 };
423
424 template<typename Indirect>
425 class Pointer
426 {
427 private:
428 Indirect m_pointed;
429
430 public:
431 explicit Pointer(const Indirect &pointed)
432 noexcept(std::is_nothrow_copy_constructible_v<Indirect>)
433 : m_pointed(pointed) {}
434 explicit Pointer(Indirect &&pointed)
435 noexcept(std::is_nothrow_move_constructible_v<Indirect>)
436 : m_pointed(std::move(pointed)) {}
437
438 Reference<Indirect> operator*()
439 const noexcept(std::is_nothrow_copy_constructible_v<Indirect>)
440 {
441 return Reference<Indirect>(m_pointed);
442 }
443
444 operator ConstPointer<Indirect>() const
445 noexcept(std::is_nothrow_copy_constructible_v<Indirect>)
446 {
447 return ConstPointer<Indirect>(m_pointed);
448 }
449 };
450
451 template <typename T, typename... Args,
452 if_constructible<T, Args...> = true>
453 explicit QVariant(std::in_place_type_t<T>, Args&&... args)
454 noexcept(is_noexcept_constructible<q20::remove_cvref_t<T>, Args...>::value)
455 : QVariant(std::in_place, QMetaType::fromType<q20::remove_cvref_t<T>>() )
456 {
457 void *data = const_cast<void *>(constData());
458 new (data) T(std::forward<Args>(args)...);
459 }
460
461 template <typename T, typename U, typename... Args,
462 if_constructible<T, std::initializer_list<U> &, Args...> = true>
463 explicit QVariant(std::in_place_type_t<T>, std::initializer_list<U> il, Args&&... args)
464 noexcept(is_noexcept_constructible<q20::remove_cvref_t<T>,
465 std::initializer_list<U> &,
466 Args...
467 >::value)
468 : QVariant(std::in_place, QMetaType::fromType<q20::remove_cvref_t<T>>())
469 {
470 void *data = const_cast<void *>(constData());
471 new (data) T(il, std::forward<Args>(args)...);
472 }
473
474 // primitives
475 QVariant(int i) noexcept;
476 QVariant(uint ui) noexcept;
477 QVariant(qlonglong ll) noexcept;
478 QVariant(qulonglong ull) noexcept;
479 QVariant(bool b) noexcept;
480 QVariant(double d) noexcept;
481 QVariant(float f) noexcept;
482
483 // trivial, trivially-copyable or COW
484 QVariant(QChar qchar) noexcept;
485 QVariant(QDate date) noexcept;
486 QVariant(QTime time) noexcept;
487 QVariant(const QBitArray &bitarray) noexcept;
488 QVariant(QBitArray &&bitarray) noexcept;
489 QVariant(const QByteArray &bytearray) noexcept;
490 QVariant(QByteArray &&bytearray) noexcept;
491 QVariant(const QDateTime &datetime) noexcept;
492 QVariant(QDateTime &&datetime) noexcept;
493 QVariant(const QHash<QString, QVariant> &hash) noexcept;
494 QVariant(QHash<QString, QVariant> &&hash) noexcept;
495 QVariant(const QJsonArray &jsonArray) noexcept;
496 QVariant(QJsonArray &&jsonArray) noexcept;
497 QVariant(const QJsonObject &jsonObject) noexcept;
498 QVariant(QJsonObject &&jsonObject) noexcept;
499 QVariant(const QList<QVariant> &list) noexcept;
500 QVariant(QList<QVariant> &&list) noexcept;
501 QVariant(const QLocale &locale) noexcept;
502 QVariant(QLocale &&locale) noexcept;
503 QVariant(const QMap<QString, QVariant> &map) noexcept;
504 QVariant(QMap<QString, QVariant> &&map) noexcept;
505 QVariant(const QRegularExpression &re) noexcept;
506 QVariant(QRegularExpression &&re) noexcept;
507 QVariant(const QString &string) noexcept;
508 QVariant(QString &&string) noexcept;
509 QVariant(const QStringList &stringlist) noexcept;
510 QVariant(QStringList &&stringlist) noexcept;
511 QVariant(const QUrl &url) noexcept;
512 QVariant(QUrl &&url) noexcept;
513
514 // conditionally noexcept trivial or trivially-copyable
515 // (most of these are noexcept on 64-bit)
516 QVariant(const QJsonValue &jsonValue) noexcept(Private::FitsInInternalSize<sizeof(CborValueStandIn)>);
517 QVariant(QJsonValue &&jsonValue) noexcept(Private::FitsInInternalSize<sizeof(CborValueStandIn)>);
518 QVariant(const QModelIndex &modelIndex) noexcept(Private::FitsInInternalSize<8 + 2 * sizeof(quintptr)>);
519 QVariant(QUuid uuid) noexcept(Private::FitsInInternalSize<16>);
520 QVariant(QSize size) noexcept;
521 QVariant(QSizeF size) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>);
522 QVariant(QPoint pt) noexcept;
523 QVariant(QPointF pt) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>);
524 QVariant(QLine line) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>);
525 QVariant(QLineF line) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>);
526 QVariant(QRect rect) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>);
527 QVariant(QRectF rect) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>);
528
529 // not noexcept
530 QVariant(const QEasingCurve &easing) noexcept(false);
531 QVariant(QEasingCurve &&easing) noexcept;
532 QVariant(const QJsonDocument &jsonDocument) noexcept(false);
533 QVariant(QJsonDocument &&jsonDocument) noexcept;
534 QVariant(const QPersistentModelIndex &modelIndex) noexcept(false);
535 QVariant(QPersistentModelIndex &&modelIndex) noexcept;
536
537#ifndef QT_NO_CAST_FROM_ASCII
538 QT_ASCII_CAST_WARN QVariant(const char *str) noexcept(false)
539 : QVariant(QString::fromUtf8(str))
540 {}
541#endif
542 QVariant(QLatin1StringView string) noexcept(false); // converts to QString
543
544#if !defined(Q_CC_GHS)
545 // GHS has an ICE with this code; use the simplified version below
546 template <typename T,
547 std::enable_if_t<std::disjunction_v<std::is_pointer<T>, std::is_member_pointer<T>>, bool> = false>
548 QVariant(T) = delete;
549#else
550 QVariant(const volatile void *) = delete;
551#endif
552
553#if QT_CORE_REMOVED_SINCE(6, 5)
554 QVariant(const QSize &size);
555 QVariant(const QSizeF &size);
556 QVariant(const QPoint &pt);
557 QVariant(const QPointF &pt);
558 QVariant(const QLine &line);
559 QVariant(const QLineF &line);
560 QVariant(const QRect &rect);
561 QVariant(const QRectF &rect);
562 QVariant(const QUuid &uuid);
563#endif
564
565 QVariant& operator=(const QVariant &other);
566 inline QVariant(QVariant &&other) noexcept : d(other.d)
567 { other.d = Private(); }
568 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QVariant)
569
570 inline void swap(QVariant &other) noexcept { std::swap(d, other.d); }
571
572 int userType() const { return typeId(); }
573 int typeId() const
574 {
575 // QVariant types are always registered (see fromMetaType())
576 const QtPrivate::QMetaTypeInterface *mt = metaType().iface();
577 if (!mt)
578 return 0;
579 int id = mt->typeId.loadRelaxed();
580 Q_PRESUME(id > 0);
581 return id;
582 }
583
584 QT_CORE_INLINE_SINCE(6, 10)
585 const char *typeName() const;
586 QT_CORE_INLINE_SINCE(6, 10)
587 QMetaType metaType() const;
588
589 bool canConvert(QMetaType targetType) const
590 { return QMetaType::canConvert(d.type(), targetType); }
591 bool convert(QMetaType type);
592
593 bool canView(QMetaType targetType) const
594 { return QMetaType::canView(d.type(), targetType); }
595
596#if QT_DEPRECATED_SINCE(6, 0)
597 QT_DEPRECATED_VERSION_6_0
598 bool canConvert(int targetTypeId) const
599 { return QMetaType::canConvert(d.type(), QMetaType(targetTypeId)); }
600 QT_DEPRECATED_VERSION_6_0
601 bool convert(int targetTypeId)
602 { return convert(QMetaType(targetTypeId)); }
603#endif
604
605 inline bool isValid() const;
606 bool isNull() const;
607
608 void clear();
609
610 void detach();
611 inline bool isDetached() const;
612
613 int toInt(bool *ok = nullptr) const;
614 uint toUInt(bool *ok = nullptr) const;
615 qlonglong toLongLong(bool *ok = nullptr) const;
616 qulonglong toULongLong(bool *ok = nullptr) const;
617 bool toBool() const;
618 double toDouble(bool *ok = nullptr) const;
619 float toFloat(bool *ok = nullptr) const;
620 qreal toReal(bool *ok = nullptr) const;
621 QByteArray toByteArray() const;
622 QBitArray toBitArray() const;
623 QString toString() const;
624 QStringList toStringList() const;
625 QChar toChar() const;
626 QDate toDate() const;
627 QTime toTime() const;
628 QDateTime toDateTime() const;
629 QList<QVariant> toList() const;
630 QMap<QString, QVariant> toMap() const;
631 QHash<QString, QVariant> toHash() const;
632
633 QPoint toPoint() const;
634 QPointF toPointF() const;
635 QRect toRect() const;
636 QSize toSize() const;
637 QSizeF toSizeF() const;
638 QLine toLine() const;
639 QLineF toLineF() const;
640 QRectF toRectF() const;
641 QLocale toLocale() const;
642#if QT_CONFIG(regularexpression)
643 QRegularExpression toRegularExpression() const;
644#endif // QT_CONFIG(regularexpression)
645#if QT_CONFIG(easingcurve)
646 QEasingCurve toEasingCurve() const;
647#endif
648 QUuid toUuid() const;
649 QUrl toUrl() const;
650 QJsonValue toJsonValue() const;
651 QJsonObject toJsonObject() const;
652 QJsonArray toJsonArray() const;
653 QJsonDocument toJsonDocument() const;
654#if QT_CONFIG(itemmodel)
655 QModelIndex toModelIndex() const;
656 QPersistentModelIndex toPersistentModelIndex() const;
657#endif
658
659#ifndef QT_NO_DATASTREAM
660 void load(QDataStream &ds);
661 void save(QDataStream &ds) const;
662#endif
663#if QT_DEPRECATED_SINCE(6, 0)
664 QT_WARNING_PUSH
665 QT_WARNING_DISABLE_DEPRECATED
666 QT_DEPRECATED_VERSION_X_6_0("Use the constructor taking a QMetaType instead.")
667 explicit QVariant(Type type)
668 : QVariant(QMetaType(int(type)))
669 {}
670 QT_DEPRECATED_VERSION_X_6_0("Use typeId() or metaType().")
671 Type type() const
672 {
673 int type = d.type().rawId();
674 return type >= QMetaType::User ? UserType : static_cast<Type>(type);
675 }
676 QT_DEPRECATED_VERSION_6_0
677 static const char *typeToName(int typeId)
678 { return QMetaType(typeId).name(); }
679 QT_DEPRECATED_VERSION_6_0
680 static Type nameToType(const char *name)
681 {
682 int metaType = QMetaType::fromName(name).rawId();
683 return metaType <= int(UserType) ? QVariant::Type(metaType) : UserType;
684 }
685 QT_WARNING_POP
686#endif
687
688 void *data();
689 const void *constData() const
690 { return d.storage(); }
691 inline const void *data() const { return constData(); }
692
693private:
694 template <typename T>
695 void verifySuitableForEmplace()
696 {
697 static_assert(!std::is_reference_v<T>,
698 "QVariant does not support reference types");
699 static_assert(!std::is_const_v<T>,
700 "QVariant does not support const types");
701 static_assert(std::is_copy_constructible_v<T>,
702 "QVariant requires that the type is copyable");
703 static_assert(std::is_destructible_v<T>,
704 "QVariant requires that the type is destructible");
705 }
706
707 template <typename T, typename... Args>
708 T &emplaceImpl(Args&&... args)
709 {
710 verifySuitableForEmplace<T>();
711 auto data = static_cast<T *>(prepareForEmplace(QMetaType::fromType<T>()));
712 return *q20::construct_at(data, std::forward<Args>(args)...);
713 }
714
715public:
716 template <typename T, typename... Args,
717 if_constructible<T, Args...> = true>
718 T &emplace(Args&&... args)
719 {
720 return emplaceImpl<T>(std::forward<Args>(args)...);
721 }
722
723 template <typename T, typename U, typename... Args,
724 if_constructible<T, std::initializer_list<U> &, Args...> = true>
725 T &emplace(std::initializer_list<U> list, Args&&... args)
726 {
727 return emplaceImpl<T>(list, std::forward<Args>(args)...);
728 }
729
730 template<typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, QVariant>>>
731 void setValue(T &&avalue)
732 {
733 using VT = std::decay_t<T>;
734 QMetaType metaType = QMetaType::fromType<VT>();
735 // If possible we reuse the current QVariant private.
736 if (isDetached() && d.type() == metaType) {
737 *reinterpret_cast<VT *>(const_cast<void *>(constData())) = std::forward<T>(avalue);
738 d.is_null = false;
739 } else {
740 *this = QVariant::fromValue<VT>(std::forward<T>(avalue));
741 }
742 }
743
744 void setValue(const QVariant &avalue)
745 {
746 *this = avalue;
747 }
748
749 void setValue(QVariant &&avalue)
750 {
751 *this = std::move(avalue);
752 }
753
754 template<typename T>
755 inline T value() const &
756 { return qvariant_cast<T>(*this); }
757
758 template<typename T>
759 inline T view()
760 {
761 T t{};
762 QMetaType::view(metaType(), data(), QMetaType::fromType<T>(), &t);
763 return t;
764 }
765
766 template<typename T>
767 inline T value() &&
768 { return qvariant_cast<T>(std::move(*this)); }
769
770 template<typename T, if_rvalue<T> = true>
771#ifndef Q_QDOC
772 /* needs is_copy_constructible for variants semantics, is_move_constructible so that moveConstruct works
773 (but copy_constructible implies move_constructble, so don't bother checking)
774 */
775 static inline auto fromValue(T &&value)
776 noexcept(std::is_nothrow_copy_constructible_v<T> && Private::CanUseInternalSpace<T>)
777 -> std::enable_if_t<std::conjunction_v<std::is_copy_constructible<T>,
778 std::is_destructible<T>>, QVariant>
779#else
780 static inline QVariant fromValue(T &&value)
781#endif
782 {
783 // handle special cases
784 using Type = std::remove_cv_t<T>;
785 if constexpr (std::is_null_pointer_v<Type>)
786 return QVariant::fromMetaType(QMetaType::fromType<std::nullptr_t>());
787 else if constexpr (std::is_same_v<Type, QVariant>)
788 return std::forward<T>(value);
789 else if constexpr (std::is_same_v<Type, std::monostate>)
790 return QVariant();
791 QMetaType mt = QMetaType::fromType<Type>();
792 mt.registerType(); // we want the type stored in QVariant to always be registered
793
794 // We only try to move if the type is actually moveable and not if T is const
795 // as in const int i; QVariant::fromValue(std::move(i));
796 if constexpr (std::conjunction_v<std::is_move_constructible<Type>, std::negation<std::is_const<T>>>)
797 return moveConstruct(QMetaType::fromType<Type>(), std::addressof(value));
798 else
799 return copyConstruct(mt, std::addressof(value));
800 }
801
802 template<typename T>
803#ifndef Q_QDOC
804 static inline auto fromValue(const T &value)
805 noexcept(std::is_nothrow_copy_constructible_v<T> && Private::CanUseInternalSpace<T>)
806 -> std::enable_if_t<std::is_copy_constructible_v<T> && std::is_destructible_v<T>, QVariant>
807#else
808 static inline QVariant fromValue(const T &value)
809#endif
810 {
811 if constexpr (std::is_null_pointer_v<T>)
812 return QVariant(QMetaType::fromType<std::nullptr_t>());
813 else if constexpr (std::is_same_v<T, QVariant>)
814 return value;
815 else if constexpr (std::is_same_v<T, std::monostate>)
816 return QVariant();
817 return QVariant(QMetaType::fromType<T>(), std::addressof(value));
818 }
819
820 template<typename... Types>
821 static inline QVariant fromStdVariant(const std::variant<Types...> &value)
822 {
823 return fromStdVariantImpl(value);
824 }
825
826 template<typename... Types>
827 static QVariant fromStdVariant(std::variant<Types...> &&value)
828 {
829 return fromStdVariantImpl(std::move(value));
830 }
831
832 static QVariant fromMetaType(QMetaType type, const void *copy = nullptr);
833
834 template<typename T>
835 bool canConvert() const
836 { return canConvert(QMetaType::fromType<T>()); }
837
838 template<typename T>
839 bool canView() const
840 { return canView(QMetaType::fromType<T>()); }
841
842 static QPartialOrdering compare(const QVariant &lhs, const QVariant &rhs);
843
844private:
845 template <typename StdVariant>
846 static QVariant fromStdVariantImpl(StdVariant &&v)
847 {
848 if (Q_UNLIKELY(v.valueless_by_exception()))
849 return QVariant();
850 auto visitor = [](auto &&arg) {
851 return QVariant::fromValue(q23::forward_like<StdVariant>(arg));
852 };
853 return std::visit(visitor, std::forward<StdVariant>(v));
854 }
855
856 friend bool comparesEqual(const QVariant &a, const QVariant &b)
857 { return a.equals(b); }
858 Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(QVariant)
859
860#ifndef QT_NO_DEBUG_STREAM
861 template <typename T>
862 friend auto operator<<(const QDebug &debug, const T &variant) -> std::enable_if_t<std::is_same_v<T, QVariant>, QDebug> {
863 return variant.qdebugHelper(debug);
864 }
865 QDebug qdebugHelper(QDebug) const;
866#endif
867
868 template <typename T, typename Variant> static constexpr
869 bool canGetTypeFromVariant(Variant *v) noexcept
870 {
871 if (!v)
872 return false;
873 if (std::is_const_v<Variant> && v->d.is_null)
874 return false; // (const) data() will not detach from is_null
875
876 using NonConstT = std::remove_const_t<std::remove_pointer_t<T>>;
877 if constexpr (std::is_pointer_v<T> && !std::is_same_v<T, NonConstT *>) {
878 if (v->d.type() == QMetaType::fromType<NonConstT *>())
879 return true;
880 }
881 return v->d.type() == QMetaType::fromType<T>();
882 }
883
884 template <typename T> T *typedData()
885 {
886 Q_PRE(canGetTypeFromVariant<T>(this));
887 return static_cast<T *>(data()); // detaches if necessary
888 }
889
890 template <typename T> const T *typedData() const
891 {
892 Q_PRE(canGetTypeFromVariant<T>(this));
893 return &d.get<T>();
894 }
895
896 template <typename T>
897 friend T *get_if(QVariant *v) noexcept
898 {
899 if (!canGetTypeFromVariant<T>(v))
900 return nullptr;
901 return v->typedData<T>();
902 }
903 template <typename T>
904 friend const T *get_if(const QVariant *v) noexcept
905 {
906 if (!canGetTypeFromVariant<T>(v))
907 return nullptr;
908 return v->typedData<const T>();
909 }
910
911#define Q_MK_GET(CONST, REF)
912 template <typename T> friend CONST T REF get(CONST QVariant REF v)
913 { return static_cast<CONST T REF>(*v.typedData<T>()); }
914 /* end */
915 Q_MK_GET(, &)
916 Q_MK_GET(const, &)
917 Q_MK_GET(, &&)
918 Q_MK_GET(const, &&)
919#undef Q_MK_GET
920
921 static QVariant moveConstruct(QMetaType type, void *data);
922 static QVariant copyConstruct(QMetaType type, const void *data);
923
924 template<typename T>
925 friend inline T qvariant_cast(const QVariant &);
926 template<typename T>
927 friend inline T qvariant_cast(QVariant &&);
928
929protected:
930 Private d;
931
932#if QT_REMOVAL_QT7_DEPRECATED_SINCE(6, 16)
933 // These were \internal, so no message in _X.
934 QT_DEPRECATED_VERSION_6_16
935 void create(int type, const void *copy);
936 QT_DEPRECATED_VERSION_6_16
937 void create(QMetaType type, const void *copy);
938 QT_DEPRECATED_VERSION_6_16
939 bool convert(int type, void *ptr) const;
940 QT_DEPRECATED_VERSION_6_16
941 bool view(int type, void *ptr);
942#endif
943 bool equals(const QVariant &other) const;
944
945private:
946 // force compile error, prevent QVariant(bool) to be called
947 inline QVariant(void *) = delete;
948 // QVariant::Type is marked as \obsolete, but we don't want to
949 // provide a constructor from its intended replacement,
950 // QMetaType::Type, instead, because the idea behind these
951 // constructors is flawed in the first place. But we also don't
952 // want QVariant(QMetaType::String) to compile and falsely be an
953 // int variant, so delete this constructor:
954 QVariant(QMetaType::Type) = delete;
955
956 // used to setup the QVariant internals for the "real" inplace ctor
957 QVariant(std::in_place_t, QMetaType type);
958 // helper for emplace
959 void *prepareForEmplace(QMetaType type);
960
961 // These constructors don't create QVariants of the type associated
962 // with the enum, as expected, but they would create a QVariant of
963 // type int with the value of the enum value.
964 // Use QVariant v = QColor(Qt::red) instead of QVariant v = Qt::red for
965 // example.
966 QVariant(Qt::GlobalColor) = delete;
967 QVariant(Qt::BrushStyle) = delete;
968 QVariant(Qt::PenStyle) = delete;
969 QVariant(Qt::CursorShape) = delete;
970#ifdef QT_NO_CAST_FROM_ASCII
971 // force compile error when implicit conversion is not wanted
972 inline QVariant(const char *) = delete;
973#endif
974public:
975 typedef Private DataPtr;
976 inline DataPtr &data_ptr() { return d; }
977 inline const DataPtr &data_ptr() const { return d; }
978};
979
980inline bool QVariant::isValid() const
981{
982 return d.type().isValid(QT6_CALL_NEW_OVERLOAD);
983}
984
985#ifndef QT_NO_DATASTREAM
986Q_CORE_EXPORT QDataStream &operator>>(QDataStream &s, QVariant &p);
987Q_CORE_EXPORT QDataStream &operator<<(QDataStream &s, const QVariant &p);
988
989#if QT_DEPRECATED_SINCE(6, 0)
990QT_WARNING_PUSH
991QT_WARNING_DISABLE_DEPRECATED
992QT_DEPRECATED_VERSION_6_0
993inline QDataStream &operator>>(QDataStream &s, QVariant::Type &p)
994{
995 quint32 u;
996 s >> u;
997 p = static_cast<QVariant::Type>(u);
998 return s;
999}
1000QT_DEPRECATED_VERSION_6_0
1001inline QDataStream &operator<<(QDataStream &s, const QVariant::Type p)
1002{
1003 s << static_cast<quint32>(p);
1004 return s;
1005}
1006QT_WARNING_POP
1007#endif
1008
1009#endif
1010
1011#if QT_CORE_INLINE_IMPL_SINCE(6, 10)
1012QMetaType QVariant::metaType() const
1013{
1014 return d.type();
1015}
1016
1017const char *QVariant::typeName() const
1018{
1019 return d.type().name();
1020}
1021#endif
1022
1023inline bool QVariant::isDetached() const
1024{ return !d.is_shared || d.data.shared->ref.loadRelaxed() == 1; }
1025
1026inline void swap(QVariant &value1, QVariant &value2) noexcept
1027{ value1.swap(value2); }
1028
1029template<typename Indirect>
1030inline QVariant::ConstReference<Indirect>::ConstReference(const Reference<Indirect> &nonConst)
1031 noexcept(std::is_nothrow_copy_constructible_v<Indirect>)
1032 : ConstReference(nonConst.m_referred)
1033{
1034}
1035
1036#ifndef QT_MOC
1037
1038namespace QtPrivate {
1039template<typename T> inline T qvariant_cast_qmetatype_converted(const QVariant &v, QMetaType targetType)
1040{
1041 T t{};
1042 QMetaType::convert(v.metaType(), v.constData(), targetType, &t);
1043 return t;
1044}
1045} // namespace QtPrivate
1046
1047template<typename T> inline T qvariant_cast(const QVariant &v)
1048{
1049 if (const T *ptr = get_if<T>(&v))
1050 return *ptr;
1051
1052 QMetaType targetType = QMetaType::fromType<T>();
1053 return QtPrivate::qvariant_cast_qmetatype_converted<T>(v, targetType);
1054}
1055
1056template<typename T> inline T qvariant_cast(QVariant &&v)
1057{
1058 if (const T *ptr = get_if<T>(&std::as_const(v))) {
1059 // we can only move from this if not sharing
1060 if constexpr (QVariant::Private::FitsInInternalSize<sizeof(T)>) {
1061 // If T in principle fits into the internal space, it may be using
1062 // it (depending on e.g. QTypeInfo, which, generally, can change
1063 // from version to version, so we need to check is_shared:
1064 if (!v.d.is_shared)
1065 return std::move(*const_cast<T *>(ptr));
1066 }
1067 // Otherwise, it cannot possibly be using internal space:
1068 Q_ASSERT(v.d.is_shared);
1069 if (v.d.data.shared->ref.loadRelaxed() == 1)
1070 return std::move(*const_cast<T *>(ptr));
1071 else
1072 return *ptr;
1073 }
1074 if constexpr (std::is_same_v<T, QVariant>) {
1075 // if the metatype doesn't match, but we want a QVariant, just return the current variant
1076 return v;
1077 }
1078
1079 QMetaType targetType = QMetaType::fromType<T>();
1080 return QtPrivate::qvariant_cast_qmetatype_converted<T>(v, targetType);
1081}
1082
1083# ifndef QT_NO_VARIANT
1084template<> inline QVariant qvariant_cast<QVariant>(const QVariant &v)
1085{
1086 if (v.metaType().id() == QMetaType::QVariant)
1087 return *reinterpret_cast<const QVariant *>(v.constData());
1088 return v;
1089}
1090# endif
1091
1092#endif // QT_MOC
1093
1094#ifndef QT_NO_DEBUG_STREAM
1095#if QT_DEPRECATED_SINCE(6, 0)
1096QT_WARNING_PUSH
1097QT_WARNING_DISABLE_DEPRECATED
1098QT_DEPRECATED_VERSION_6_0
1099Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type);
1100QT_WARNING_POP
1101#endif
1102#endif
1103
1104namespace QtPrivate {
1105class Q_CORE_EXPORT QVariantTypeCoercer
1106{
1107public:
1108 // ### Qt7: Pass QMetaType as value rather than const ref.
1109 const void *convert(const QVariant &value, const QMetaType &type);
1110 const void *coerce(const QVariant &value, const QMetaType &type);
1111
1112private:
1114};
1115}
1116
1117#if QT_DEPRECATED_SINCE(6, 15)
1118QT_WARNING_PUSH
1119QT_WARNING_DISABLE_DEPRECATED
1120
1121template<typename Pointer> class
1122QT_DEPRECATED_VERSION_X_6_15("Use QVariant::Reference instead.")
1123QVariantRef
1124{
1125private:
1126 const Pointer *m_pointer = nullptr;
1127
1128public:
1129 explicit QVariantRef(const Pointer *reference) : m_pointer(reference) {}
1130 QVariantRef(const QVariantRef &) = default;
1131 QVariantRef(QVariantRef &&) = default;
1132 ~QVariantRef() = default;
1133
1134 operator QVariant() const;
1135 QVariantRef &operator=(const QVariant &value);
1136 QVariantRef &operator=(const QVariantRef &value) { return operator=(QVariant(value)); }
1137 QVariantRef &operator=(QVariantRef &&value) { return operator=(QVariant(value)); }
1138
1139 friend void swap(QVariantRef a, QVariantRef b)
1140 {
1141 QVariant tmp = a;
1142 a = b;
1143 b = std::move(tmp);
1144 }
1145};
1146
1147// Keep this a single long line, otherwise syncqt doesn't create a class forwarding header
1148class Q_CORE_EXPORT QT_DEPRECATED_VERSION_X_6_15("Use QVariant::ConstPointer instead.") QVariantConstPointer
1149{
1150private:
1151 QVariant m_variant;
1152
1153public:
1154 explicit QVariantConstPointer(QVariant variant);
1155
1156 QVariant operator*() const;
1157 const QVariant *operator->() const;
1158};
1159
1160template<typename Pointer> class
1161QT_DEPRECATED_VERSION_X_6_15("Use QVariant::Pointer instead.")
1162QVariantPointer
1163{
1164private:
1165 const Pointer *m_pointer = nullptr;
1166
1167public:
1168 explicit QVariantPointer(const Pointer *pointer) : m_pointer(pointer) {}
1169 QVariantRef<Pointer> operator*() const { return QVariantRef<Pointer>(m_pointer); }
1170 Pointer operator->() const { return *m_pointer; }
1171};
1172
1173QT_WARNING_POP
1174#endif // QT_DEPRECATED_SINCE(6, 15)
1175
1176QT_END_NAMESPACE
1177
1178#endif // QVARIANT_H
\inmodule QtCore\reentrant
Definition qdatastream.h:50
\inmodule QtCore
\inmodule QtCore\reentrant
Definition qpoint.h:232
\inmodule QtCore\reentrant
Definition qpoint.h:30
\inmodule QtCore
Definition qvariant.h:68
Combined button and popup list for selecting options.
T qvariant_cast_qmetatype_converted(const QVariant &v, QMetaType targetType)
Definition qvariant.h:1039
static QString appendSlashIfNeeded(const QString &path)
#define Q_MK_GET(CONST, REF)
Definition qvariant.h:911
T qvariant_cast(QVariant &&v)
Definition qvariant.h:1056
T qvariant_cast(const QVariant &)
Definition qvariant.h:1047
void swap(QVariant &value1, QVariant &value2) noexcept
Definition qvariant.h:1026