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