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