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