1// Copyright (C) 2022 The Qt Company Ltd.
2// Copyright (C) 2021 Intel Corporation.
3// Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
4// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
5
6#include "qvariant_p.h"
7#include "qbitarray.h"
8#include "qbytearray.h"
9#include "qdatastream.h"
10#include "qdebug.h"
11#include "qmap.h"
12#include "qhash.h"
13#include "qdatetime.h"
14#if QT_CONFIG(easingcurve)
15#include "qeasingcurve.h"
16#endif
17#include "qlist.h"
18#if QT_CONFIG(regularexpression)
19#include "qregularexpression.h"
20#endif
21#include "qstring.h"
22#include "qstringlist.h"
23#include "qurl.h"
24#include "qlocale.h"
25#include "quuid.h"
26#if QT_CONFIG(itemmodel)
27#include "qabstractitemmodel.h"
28#endif
29#ifndef QT_BOOTSTRAPPED
30#include "qcborarray.h"
31#include "qcborcommon.h"
32#include "qcbormap.h"
33#include "qjsonvalue.h"
34#include "qjsonobject.h"
35#include "qjsonarray.h"
36#include "qjsondocument.h"
37#include "qbytearraylist.h"
38#endif
39#include "private/qlocale_p.h"
40#include "qmetatype_p.h"
41#include <qmetaobject.h>
42
43#ifndef QT_NO_GEOM_VARIANT
44#include "qsize.h"
45#include "qpoint.h"
46#include "qrect.h"
47#include "qline.h"
48#endif
49
50#include <memory>
51
52#include <cmath>
53#include <float.h>
54#include <cstring>
55
56QT_BEGIN_NAMESPACE
57
58using namespace Qt::StringLiterals;
59
60namespace { // anonymous used to hide QVariant handlers
61
62static qlonglong qMetaTypeNumberBySize(const QVariant::Private *d)
63{
64 switch (d->typeInterface()->size) {
65 case 1:
66 return d->get<signed char>();
67 case 2:
68 return d->get<short>();
69 case 4:
70 return d->get<int>();
71 case 8:
72 return d->get<qlonglong>();
73 }
74 Q_UNREACHABLE_RETURN(0);
75}
76
77static qlonglong qMetaTypeNumber(const QVariant::Private *d)
78{
79 switch (d->typeInterface()->typeId) {
80 case QMetaType::Int:
81 case QMetaType::LongLong:
82 case QMetaType::Char:
83 case QMetaType::SChar:
84 case QMetaType::Short:
85 case QMetaType::Long:
86 return qMetaTypeNumberBySize(d);
87 case QMetaType::Float:
88 return qRound64(f: d->get<float>());
89 case QMetaType::Double:
90 return qRound64(d: d->get<double>());
91#ifndef QT_BOOTSTRAPPED
92 case QMetaType::QJsonValue:
93 return d->get<QJsonValue>().toDouble();
94 case QMetaType::QCborValue:
95 return d->get<QCborValue>().toInteger();
96#endif
97 }
98 Q_UNREACHABLE_RETURN(0);
99}
100
101static qulonglong qMetaTypeUNumber(const QVariant::Private *d)
102{
103 switch (d->typeInterface()->size) {
104 case 1:
105 return d->get<unsigned char>();
106 case 2:
107 return d->get<unsigned short>();
108 case 4:
109 return d->get<unsigned int>();
110 case 8:
111 return d->get<qulonglong>();
112 }
113 Q_UNREACHABLE_RETURN(0);
114}
115
116static std::optional<qlonglong> qConvertToNumber(const QVariant::Private *d, bool allowStringToBool = false)
117{
118 bool ok;
119 switch (d->typeInterface()->typeId) {
120 case QMetaType::QString: {
121 const QString &s = d->get<QString>();
122 if (qlonglong l = s.toLongLong(ok: &ok); ok)
123 return l;
124 if (allowStringToBool) {
125 if (s == "false"_L1 || s == "0"_L1)
126 return 0;
127 if (s == "true"_L1 || s == "1"_L1)
128 return 1;
129 }
130 return std::nullopt;
131 }
132 case QMetaType::QChar:
133 return d->get<QChar>().unicode();
134 case QMetaType::QByteArray:
135 if (qlonglong l = d->get<QByteArray>().toLongLong(ok: &ok); ok)
136 return l;
137 return std::nullopt;
138 case QMetaType::Bool:
139 return qlonglong(d->get<bool>());
140#ifndef QT_BOOTSTRAPPED
141 case QMetaType::QCborValue:
142 if (!d->get<QCborValue>().isInteger() && !d->get<QCborValue>().isDouble())
143 break;
144 return qMetaTypeNumber(d);
145 case QMetaType::QJsonValue:
146 if (!d->get<QJsonValue>().isDouble())
147 break;
148 Q_FALLTHROUGH();
149#endif
150 case QMetaType::Double:
151 case QMetaType::Int:
152 case QMetaType::Char:
153 case QMetaType::SChar:
154 case QMetaType::Short:
155 case QMetaType::Long:
156 case QMetaType::Float:
157 case QMetaType::LongLong:
158 return qMetaTypeNumber(d);
159 case QMetaType::ULongLong:
160 case QMetaType::UInt:
161 case QMetaType::UChar:
162 case QMetaType::Char16:
163 case QMetaType::Char32:
164 case QMetaType::UShort:
165 case QMetaType::ULong:
166 return qlonglong(qMetaTypeUNumber(d));
167 }
168
169 if (d->typeInterface()->flags & QMetaType::IsEnumeration
170 || d->typeInterface()->typeId == QMetaType::QCborSimpleType)
171 return qMetaTypeNumberBySize(d);
172
173 return std::nullopt;
174}
175
176static std::optional<double> qConvertToRealNumber(const QVariant::Private *d)
177{
178 bool ok;
179 switch (d->typeInterface()->typeId) {
180 case QMetaType::QString:
181 if (double r = d->get<QString>().toDouble(ok: &ok); ok)
182 return r;
183 return std::nullopt;
184 case QMetaType::Double:
185 return d->get<double>();
186 case QMetaType::Float:
187 return double(d->get<float>());
188 case QMetaType::Float16:
189 return double(d->get<qfloat16>());
190 case QMetaType::ULongLong:
191 case QMetaType::UInt:
192 case QMetaType::UChar:
193 case QMetaType::Char16:
194 case QMetaType::Char32:
195 case QMetaType::UShort:
196 case QMetaType::ULong:
197 return double(qMetaTypeUNumber(d));
198#ifndef QT_BOOTSTRAPPED
199 case QMetaType::QCborValue:
200 return d->get<QCborValue>().toDouble();
201 case QMetaType::QJsonValue:
202 return d->get<QJsonValue>().toDouble();
203#endif
204 default:
205 // includes enum conversion as well as invalid types
206 if (std::optional<qlonglong> l = qConvertToNumber(d))
207 return double(*l);
208 return std::nullopt;
209 }
210}
211
212static bool isValidMetaTypeForVariant(const QtPrivate::QMetaTypeInterface *iface, const void *copy)
213{
214 using namespace QtMetaTypePrivate;
215 if (!iface || iface->size == 0)
216 return false;
217
218 Q_ASSERT(!isInterfaceFor<void>(iface)); // only void should have size 0
219 if (!isCopyConstructible(iface) || !isDestructible(iface)) {
220 // all meta types must be copyable (because QVariant is) and
221 // destructible (because QVariant owns it)
222 qWarning(msg: "QVariant: Provided metatype for '%s' does not support destruction and "
223 "copy construction", iface->name);
224 return false;
225 }
226 if (!copy && !isDefaultConstructible(iface)) {
227 // non-default-constructible types are acceptable, but not if you're
228 // asking us to construct from nothing
229 qWarning(msg: "QVariant: Cannot create type '%s' without a default constructor", iface->name);
230 return false;
231 }
232
233 return true;
234}
235
236enum CustomConstructMoveOptions {
237 UseCopy, // custom construct uses the copy ctor unconditionally
238 // future option: TryMove: uses move ctor if available, else copy ctor
239 ForceMove, // custom construct use the move ctor (which must exist)
240};
241
242enum CustomConstructNullabilityOption {
243 MaybeNull, // copy might be null, might be non-null
244 NonNull, // copy is guarantueed to be non-null
245 // future option: AlwaysNull?
246};
247
248// the type of d has already been set, but other field are not set
249template <CustomConstructMoveOptions moveOption = UseCopy, CustomConstructNullabilityOption nullability = MaybeNull>
250static void customConstruct(const QtPrivate::QMetaTypeInterface *iface, QVariant::Private *d,
251 std::conditional_t<moveOption == ForceMove, void *, const void *> copy)
252{
253 using namespace QtMetaTypePrivate;
254 Q_ASSERT(iface);
255 Q_ASSERT(iface->size);
256 Q_ASSERT(!isInterfaceFor<void>(iface));
257 Q_ASSERT(isCopyConstructible(iface));
258 Q_ASSERT(isDestructible(iface));
259 Q_ASSERT(copy || isDefaultConstructible(iface));
260 if constexpr (moveOption == ForceMove)
261 Q_ASSERT(isMoveConstructible(iface));
262 if constexpr (nullability == NonNull)
263 Q_ASSUME(copy != nullptr);
264
265 // need to check for nullptr_t here, as this can get called by fromValue(nullptr). fromValue() uses
266 // std::addressof(value) which in this case returns the address of the nullptr object.
267 // ### Qt 7: remove nullptr_t special casing
268 d->is_null = !copy QT6_ONLY(|| isInterfaceFor<std::nullptr_t>(iface));
269
270 if (QVariant::Private::canUseInternalSpace(type: iface)) {
271 d->is_shared = false;
272 if (!copy && !iface->defaultCtr)
273 return; // trivial default constructor and it's OK to build in 0-filled storage, which we've already done
274 if constexpr (moveOption == ForceMove && nullability == NonNull)
275 moveConstruct(iface, d->data.data, copy);
276 else
277 construct(iface, d->data.data, copy);
278 } else {
279 d->data.shared = customConstructShared(iface->size, iface->alignment, [=](void *where) {
280 if constexpr (moveOption == ForceMove && nullability == NonNull)
281 moveConstruct(iface, where, copy);
282 else
283 construct(iface, where, copy);
284 });
285 d->is_shared = true;
286 }
287}
288
289static void customClear(QVariant::Private *d)
290{
291 const QtPrivate::QMetaTypeInterface *iface = d->typeInterface();
292 if (!iface)
293 return;
294 if (!d->is_shared) {
295 QtMetaTypePrivate::destruct(iface, where: d->data.data);
296 } else {
297 QtMetaTypePrivate::destruct(iface, where: d->data.shared->data());
298 QVariant::PrivateShared::free(p: d->data.shared);
299 }
300}
301
302static QVariant::Private clonePrivate(const QVariant::Private &other)
303{
304 QVariant::Private d = other;
305 if (d.is_shared) {
306 d.data.shared->ref.ref();
307 } else if (const QtPrivate::QMetaTypeInterface *iface = d.typeInterface()) {
308 Q_ASSERT(d.canUseInternalSpace(iface));
309
310 // if not trivially copyable, ask to copy
311 if (iface->copyCtr)
312 QtMetaTypePrivate::copyConstruct(iface, where: d.data.data, copy: other.data.data);
313 }
314 return d;
315}
316
317} // anonymous used to hide QVariant handlers
318
319/*!
320 \class QVariant
321 \inmodule QtCore
322 \brief The QVariant class acts like a union for the most common Qt data types.
323
324 \ingroup objectmodel
325 \ingroup shared
326
327
328 Because C++ forbids unions from including types that have
329 non-default constructors or destructors, most interesting Qt
330 classes cannot be used in unions. Without QVariant, this would be
331 a problem for QObject::property() and for database work, etc.
332
333 A QVariant object holds a single value of a single typeId() at a
334 time. (Some types are multi-valued, for example a string list.)
335 You can find out what type, T, the variant holds, convert it to a
336 different type using convert(), get its value using one of the
337 toT() functions (e.g., toSize()), and check whether the type can
338 be converted to a particular type using canConvert().
339
340 The methods named toT() (e.g., toInt(), toString()) are const. If
341 you ask for the stored type, they return a copy of the stored
342 object. If you ask for a type that can be generated from the
343 stored type, toT() copies and converts and leaves the object
344 itself unchanged. If you ask for a type that cannot be generated
345 from the stored type, the result depends on the type; see the
346 function documentation for details.
347
348 Here is some example code to demonstrate the use of QVariant:
349
350 \snippet code/src_corelib_kernel_qvariant.cpp 0
351
352 You can even store QList<QVariant> and QMap<QString, QVariant>
353 values in a variant, so you can easily construct arbitrarily
354 complex data structures of arbitrary types. This is very powerful
355 and versatile, but may prove less memory and speed efficient than
356 storing specific types in standard data structures.
357
358 QVariant also supports the notion of null values. A variant is null
359 if the variant contains no initialized value, or contains a null pointer.
360
361 \snippet code/src_corelib_kernel_qvariant.cpp 1
362
363 QVariant can be extended to support other types than those
364 mentioned in the \l QMetaType::Type enum.
365 See \l{Creating Custom Qt Types}{Creating Custom Qt Types} for details.
366
367 \section1 A Note on GUI Types
368
369 Because QVariant is part of the Qt Core module, it cannot provide
370 conversion functions to data types defined in Qt GUI, such as
371 QColor, QImage, and QPixmap. In other words, there is no \c
372 toColor() function. Instead, you can use the QVariant::value() or
373 the qvariant_cast() template function. For example:
374
375 \snippet code/src_corelib_kernel_qvariant.cpp 2
376
377 The inverse conversion (e.g., from QColor to QVariant) is
378 automatic for all data types supported by QVariant, including
379 GUI-related types:
380
381 \snippet code/src_corelib_kernel_qvariant.cpp 3
382
383 \section1 Using canConvert() and convert() Consecutively
384
385 When using canConvert() and convert() consecutively, it is possible for
386 canConvert() to return true, but convert() to return false. This
387 is typically because canConvert() only reports the general ability of
388 QVariant to convert between types given suitable data; it is still
389 possible to supply data which cannot actually be converted.
390
391 For example, \c{canConvert(QMetaType::fromType<int>())} would return true
392 when called on a variant containing a string because, in principle,
393 QVariant is able to convert strings of numbers to integers.
394 However, if the string contains non-numeric characters, it cannot be
395 converted to an integer, and any attempt to convert it will fail.
396 Hence, it is important to have both functions return true for a
397 successful conversion.
398
399 \sa QMetaType
400*/
401
402/*!
403 \deprecated Use \l QMetaType::Type instead.
404 \enum QVariant::Type
405
406 This enum type defines the types of variable that a QVariant can
407 contain.
408
409 \value Invalid no type
410 \value BitArray a QBitArray
411 \value Bitmap a QBitmap
412 \value Bool a bool
413 \value Brush a QBrush
414 \value ByteArray a QByteArray
415 \value Char a QChar
416 \value Color a QColor
417 \value Cursor a QCursor
418 \value Date a QDate
419 \value DateTime a QDateTime
420 \value Double a double
421 \value EasingCurve a QEasingCurve
422 \value Uuid a QUuid
423 \value ModelIndex a QModelIndex
424 \value [since 5.5] PersistentModelIndex a QPersistentModelIndex
425 \value Font a QFont
426 \value Hash a QVariantHash
427 \value Icon a QIcon
428 \value Image a QImage
429 \value Int an int
430 \value KeySequence a QKeySequence
431 \value Line a QLine
432 \value LineF a QLineF
433 \value List a QVariantList
434 \value Locale a QLocale
435 \value LongLong a \l qlonglong
436 \value Map a QVariantMap
437 \value Transform a QTransform
438 \value Matrix4x4 a QMatrix4x4
439 \value Palette a QPalette
440 \value Pen a QPen
441 \value Pixmap a QPixmap
442 \value Point a QPoint
443 \value PointF a QPointF
444 \value Polygon a QPolygon
445 \value PolygonF a QPolygonF
446 \value Quaternion a QQuaternion
447 \value Rect a QRect
448 \value RectF a QRectF
449 \value RegularExpression a QRegularExpression
450 \value Region a QRegion
451 \value Size a QSize
452 \value SizeF a QSizeF
453 \value SizePolicy a QSizePolicy
454 \value String a QString
455 \value StringList a QStringList
456 \value TextFormat a QTextFormat
457 \value TextLength a QTextLength
458 \value Time a QTime
459 \value UInt a \l uint
460 \value ULongLong a \l qulonglong
461 \value Url a QUrl
462 \value Vector2D a QVector2D
463 \value Vector3D a QVector3D
464 \value Vector4D a QVector4D
465
466 \value UserType Base value for user-defined types.
467
468 \omitvalue LastGuiType
469 \omitvalue LastCoreType
470 \omitvalue LastType
471*/
472
473/*!
474 \fn QVariant::QVariant(QVariant &&other)
475
476 Move-constructs a QVariant instance, making it point at the same
477 object that \a other was pointing to.
478
479 \since 5.2
480*/
481
482/*!
483 \fn QVariant &QVariant::operator=(QVariant &&other)
484
485 Move-assigns \a other to this QVariant instance.
486
487 \since 5.2
488*/
489
490/*!
491 \fn QVariant::QVariant()
492
493 Constructs an invalid variant.
494*/
495
496/*!
497 \fn QVariant::create(int type, const void *copy)
498
499 \internal
500
501 Constructs a variant private of type \a type, and initializes with \a copy if
502 \a copy is not \nullptr.
503
504*/
505//### Qt 7: Remove in favor of QMetaType overload
506void QVariant::create(int type, const void *copy)
507{
508 create(type: QMetaType(type), copy);
509}
510
511/*!
512 \fn QVariant::create(int type, const void *copy)
513
514 \internal
515 \overload
516*/
517void QVariant::create(QMetaType type, const void *copy)
518{
519 *this = QVariant(type, copy);
520}
521
522/*!
523 \fn QVariant::~QVariant()
524
525 Destroys the QVariant and the contained object.
526*/
527
528QVariant::~QVariant()
529{
530 if (!d.is_shared || !d.data.shared->ref.deref())
531 customClear(d: &d);
532}
533
534/*!
535 \fn QVariant::QVariant(const QVariant &p)
536
537 Constructs a copy of the variant, \a p, passed as the argument to
538 this constructor.
539*/
540
541QVariant::QVariant(const QVariant &p)
542 : d(clonePrivate(other: p.d))
543{
544}
545
546/*!
547 \fn template <typename T, typename... Args, if_constructible<T, Args...> = true> QVariant::QVariant(std::in_place_type_t<T>, Args&&... args) noexcept(is_noexcept_constructible<q20::remove_cvref_t<T>, Args...>::value)
548
549 \since 6.6
550 Constructs a new variant containing a value of type \c T. The contained
551 value is is initialized with the arguments
552 \c{std::forward<Args>(args)...}.
553
554 This overload only participates in overload resolution if \c T can be
555 constructed from \a args.
556
557 This constructor is provided for STL/std::any compatibility.
558
559 \overload
560 */
561
562/*!
563
564 \fn template <typename T, typename U, typename... Args, if_constructible<T, std::initializer_list<U> &, Args...> = true> explicit QVariant::QVariant(std::in_place_type_t<T>, std::initializer_list<U> il, Args&&... args) noexcept(is_noexcept_constructible<q20::remove_cvref_t<T>, std::initializer_list<U> &, Args... >::value)
565
566 \since 6.6
567 \overload
568 This overload exists to support types with constructors taking an
569 \c initializer_list. It behaves otherwise equivalent to the
570 non-initializer list \c{in_place_type_t} overload.
571*/
572
573
574/*!
575 \fn template <typename T, typename... Args, if_constructible<T, Args...> = true> QVariant::emplace(Args&&... args)
576
577 \since 6.6
578 Replaces the object currently held in \c{*this} with an object of
579 type \c{T}, constructed from \a{args}\c{...}. If \c{*this} was non-null,
580 the previously held object is destroyed first.
581 If possible, this method will reuse memory allocated by the QVariant.
582 Returns a reference to the newly-created object.
583 */
584
585/*!
586 \fn template <typename T, typename U, typename... Args, if_constructible<T, std::initializer_list<U> &, Args...> = true> QVariant::emplace(std::initializer_list<U> list, Args&&... args)
587
588 \since 6.6
589 \overload
590 This overload exists to support types with constructors taking an
591 \c initializer_list. It behaves otherwise equivalent to the
592 non-initializer list overload.
593*/
594
595QVariant::QVariant(std::in_place_t, QMetaType type) : d(type.iface())
596{
597 // we query the metatype instead of detecting it at compile time
598 // so that we can change relocatability of internal types
599 if (!Private::canUseInternalSpace(type: type.iface())) {
600 d.data.shared = PrivateShared::create(size: type.sizeOf(), align: type.alignOf());
601 d.is_shared = true;
602 }
603}
604
605/*!
606 \internal
607 Returns a pointer to data suitable for placement new
608 of an object of type \a type
609 Changes the variant's metatype to \a type
610 */
611void *QVariant::prepareForEmplace(QMetaType type)
612{
613 /* There are two cases where we can reuse the existing storage
614 (1) The new type fits in QVariant's SBO storage
615 (2) We are using the externally allocated storage, the variant is
616 detached, and the new type fits into the existing storage.
617 In all other cases (3), we cannot reuse the storage.
618 */
619 auto typeFits = [&] {
620 auto newIface = type.iface();
621 auto oldIface = d.typeInterface();
622 auto newSize = PrivateShared::computeAllocationSize(size: newIface->size, align: newIface->alignment);
623 auto oldSize = PrivateShared::computeAllocationSize(size: oldIface->size, align: oldIface->alignment);
624 return newSize <= oldSize;
625 };
626 if (Private::canUseInternalSpace(type: type.iface())) { // (1)
627 clear();
628 d.packedType = quintptr(type.iface()) >> 2;
629 return d.data.data;
630 } else if (d.is_shared && isDetached() && typeFits()) { // (2)
631 QtMetaTypePrivate::destruct(iface: d.typeInterface(), where: d.data.shared->data());
632 // compare QVariant::PrivateShared::create
633 const auto ps = d.data.shared;
634 const auto align = type.alignOf();
635 ps->offset = PrivateShared::computeOffset(ps, align);
636 d.packedType = quintptr(type.iface()) >> 2;
637 return ps->data();
638 }
639 // (3)
640 QVariant newVariant(std::in_place, type);
641 swap(other&: newVariant);
642 // const cast is safe, we're in a non-const method
643 return const_cast<void *>(d.storage());
644}
645
646/*!
647 \fn QVariant::QVariant(const QString &val) noexcept
648
649 Constructs a new variant with a string value, \a val.
650*/
651
652/*!
653 \fn QVariant::QVariant(QLatin1StringView val)
654
655 Constructs a new variant with a QString value from the Latin-1
656 string viewed by \a val.
657*/
658
659/*!
660 \fn QVariant::QVariant(const char *val)
661
662 Constructs a new variant with a string value of \a val.
663 The variant creates a deep copy of \a val into a QString assuming
664 UTF-8 encoding on the input \a val.
665
666 Note that \a val is converted to a QString for storing in the
667 variant and QVariant::userType() will return QMetaType::QString for
668 the variant.
669
670 You can disable this operator by defining \c
671 QT_NO_CAST_FROM_ASCII when you compile your applications.
672*/
673
674/*!
675 \fn QVariant::QVariant(const QStringList &val) noexcept
676
677 Constructs a new variant with a string list value, \a val.
678*/
679
680/*!
681 \fn QVariant::QVariant(const QMap<QString, QVariant> &val) noexcept
682
683 Constructs a new variant with a map of \l {QVariant}s, \a val.
684*/
685
686/*!
687 \fn QVariant::QVariant(const QHash<QString, QVariant> &val) noexcept
688
689 Constructs a new variant with a hash of \l {QVariant}s, \a val.
690*/
691
692/*!
693 \fn QVariant::QVariant(QDate val) noexcept
694
695 Constructs a new variant with a date value, \a val.
696*/
697
698/*!
699 \fn QVariant::QVariant(QTime val) noexcept
700
701 Constructs a new variant with a time value, \a val.
702*/
703
704/*!
705 \fn QVariant::QVariant(const QDateTime &val) noexcept
706
707 Constructs a new variant with a date/time value, \a val.
708*/
709
710/*!
711 \since 4.7
712 \fn QVariant::QVariant(const QEasingCurve &val)
713
714 Constructs a new variant with an easing curve value, \a val.
715*/
716
717/*!
718 \since 5.0
719 \fn QVariant::QVariant(QUuid val) noexcept
720
721 Constructs a new variant with an uuid value, \a val.
722*/
723
724/*!
725 \since 5.0
726 \fn QVariant::QVariant(const QModelIndex &val) noexcept
727
728 Constructs a new variant with a QModelIndex value, \a val.
729*/
730
731/*!
732 \since 5.5
733 \fn QVariant::QVariant(const QPersistentModelIndex &val)
734
735 Constructs a new variant with a QPersistentModelIndex value, \a val.
736*/
737
738/*!
739 \since 5.0
740 \fn QVariant::QVariant(const QJsonValue &val)
741
742 Constructs a new variant with a json value, \a val.
743*/
744
745/*!
746 \since 5.0
747 \fn QVariant::QVariant(const QJsonObject &val)
748
749 Constructs a new variant with a json object value, \a val.
750*/
751
752/*!
753 \since 5.0
754 \fn QVariant::QVariant(const QJsonArray &val)
755
756 Constructs a new variant with a json array value, \a val.
757*/
758
759/*!
760 \since 5.0
761 \fn QVariant::QVariant(const QJsonDocument &val)
762
763 Constructs a new variant with a json document value, \a val.
764*/
765
766/*!
767 \fn QVariant::QVariant(const QByteArray &val) noexcept
768
769 Constructs a new variant with a bytearray value, \a val.
770*/
771
772/*!
773 \fn QVariant::QVariant(const QBitArray &val) noexcept
774
775 Constructs a new variant with a bitarray value, \a val.
776*/
777
778/*!
779 \fn QVariant::QVariant(QPoint val) noexcept
780
781 Constructs a new variant with a point value of \a val.
782 */
783
784/*!
785 \fn QVariant::QVariant(QPointF val) noexcept
786
787 Constructs a new variant with a point value of \a val.
788 */
789
790/*!
791 \fn QVariant::QVariant(QRectF val)
792
793 Constructs a new variant with a rect value of \a val.
794 */
795
796/*!
797 \fn QVariant::QVariant(QLineF val) noexcept
798
799 Constructs a new variant with a line value of \a val.
800 */
801
802/*!
803 \fn QVariant::QVariant(QLine val) noexcept
804
805 Constructs a new variant with a line value of \a val.
806 */
807
808/*!
809 \fn QVariant::QVariant(QRect val) noexcept
810
811 Constructs a new variant with a rect value of \a val.
812 */
813
814/*!
815 \fn QVariant::QVariant(QSize val) noexcept
816
817 Constructs a new variant with a size value of \a val.
818 */
819
820/*!
821 \fn QVariant::QVariant(QSizeF val) noexcept
822
823 Constructs a new variant with a size value of \a val.
824 */
825
826/*!
827 \fn QVariant::QVariant(const QUrl &val) noexcept
828
829 Constructs a new variant with a url value of \a val.
830 */
831
832/*!
833 \fn QVariant::QVariant(int val) noexcept
834
835 Constructs a new variant with an integer value, \a val.
836*/
837
838/*!
839 \fn QVariant::QVariant(uint val) noexcept
840
841 Constructs a new variant with an unsigned integer value, \a val.
842*/
843
844/*!
845 \fn QVariant::QVariant(qlonglong val) noexcept
846
847 Constructs a new variant with a long long integer value, \a val.
848*/
849
850/*!
851 \fn QVariant::QVariant(qulonglong val) noexcept
852
853 Constructs a new variant with an unsigned long long integer value, \a val.
854*/
855
856
857/*!
858 \fn QVariant::QVariant(bool val) noexcept
859
860 Constructs a new variant with a boolean value, \a val.
861*/
862
863/*!
864 \fn QVariant::QVariant(double val) noexcept
865
866 Constructs a new variant with a floating point value, \a val.
867*/
868
869/*!
870 \fn QVariant::QVariant(float val) noexcept
871
872 Constructs a new variant with a floating point value, \a val.
873 \since 4.6
874*/
875
876/*!
877 \fn QVariant::QVariant(const QList<QVariant> &val) noexcept
878
879 Constructs a new variant with a list value, \a val.
880*/
881
882/*!
883 \fn QVariant::QVariant(QChar c) noexcept
884
885 Constructs a new variant with a char value, \a c.
886*/
887
888/*!
889 \fn QVariant::QVariant(const QLocale &l) noexcept
890
891 Constructs a new variant with a locale value, \a l.
892*/
893
894/*!
895 \fn QVariant::QVariant(const QRegularExpression &re) noexcept
896
897 \since 5.0
898
899 Constructs a new variant with the regular expression value \a re.
900*/
901
902/*! \fn QVariant::QVariant(Type type)
903 \deprecated [6.0] Use the constructor taking a QMetaType instead.
904
905 Constructs an uninitialized variant of type \a type. This will create a
906 variant in a special null state that if accessed will return a default
907 constructed value of the \a type.
908
909 \sa isNull()
910*/
911
912/*!
913 Constructs variant of type \a type, and initializes with
914 \a copy if \a copy is not \nullptr.
915
916 Note that you have to pass the address of the variable you want stored.
917
918 Usually, you never have to use this constructor, use QVariant::fromValue()
919 instead to construct variants from the pointer types represented by
920 \c QMetaType::VoidStar, and \c QMetaType::QObjectStar.
921
922 If \a type does not support copy and default construction, the variant will
923 be invalid.
924
925 \sa QVariant::fromValue(), QMetaType::Type
926*/
927QVariant::QVariant(QMetaType type, const void *copy) : d(type.iface())
928{
929 type.registerType();
930 if (isValidMetaTypeForVariant(iface: type.iface(), copy))
931 customConstruct(iface: type.iface(), d: &d, copy);
932 else
933 d = {};
934}
935
936QVariant::QVariant(int val) noexcept : d(std::piecewise_construct_t{}, val) {}
937QVariant::QVariant(uint val) noexcept : d(std::piecewise_construct_t{}, val) {}
938QVariant::QVariant(qlonglong val) noexcept : d(std::piecewise_construct_t{}, val) {}
939QVariant::QVariant(qulonglong val) noexcept : d(std::piecewise_construct_t{}, val) {}
940QVariant::QVariant(bool val) noexcept : d(std::piecewise_construct_t{}, val) {}
941QVariant::QVariant(double val) noexcept : d(std::piecewise_construct_t{}, val) {}
942QVariant::QVariant(float val) noexcept : d(std::piecewise_construct_t{}, val) {}
943
944QVariant::QVariant(const QByteArray &val) noexcept : d(std::piecewise_construct_t{}, val) {}
945QVariant::QVariant(const QBitArray &val) noexcept : d(std::piecewise_construct_t{}, val) {}
946QVariant::QVariant(const QString &val) noexcept : d(std::piecewise_construct_t{}, val) {}
947QVariant::QVariant(QChar val) noexcept : d(std::piecewise_construct_t{}, val) {}
948QVariant::QVariant(const QStringList &val) noexcept : d(std::piecewise_construct_t{}, val) {}
949
950QVariant::QVariant(QDate val) noexcept : d(std::piecewise_construct_t{}, val) {}
951QVariant::QVariant(QTime val) noexcept : d(std::piecewise_construct_t{}, val) {}
952QVariant::QVariant(const QDateTime &val) noexcept : d(std::piecewise_construct_t{}, val) {}
953
954QVariant::QVariant(const QList<QVariant> &list) noexcept : d(std::piecewise_construct_t{}, list) {}
955QVariant::QVariant(const QMap<QString, QVariant> &map) noexcept : d(std::piecewise_construct_t{}, map) {}
956QVariant::QVariant(const QHash<QString, QVariant> &hash) noexcept : d(std::piecewise_construct_t{}, hash) {}
957
958QVariant::QVariant(QLatin1StringView val) : QVariant(QString(val)) {}
959
960#if QT_CONFIG(easingcurve)
961QVariant::QVariant(const QEasingCurve &val) : d(std::piecewise_construct_t{}, val) {}
962#endif
963#ifndef QT_NO_GEOM_VARIANT
964QVariant::QVariant(QPoint pt) noexcept
965 : d(std::piecewise_construct_t{}, pt) {}
966QVariant::QVariant(QPointF pt) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>)
967 : d(std::piecewise_construct_t{}, pt) {}
968QVariant::QVariant(QRect r) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>)
969 : d(std::piecewise_construct_t{}, r) {}
970QVariant::QVariant(QRectF r) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>)
971 : d(std::piecewise_construct_t{}, r) {}
972QVariant::QVariant(QLine l) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>)
973 : d(std::piecewise_construct_t{}, l) {}
974QVariant::QVariant(QLineF l) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>)
975 : d(std::piecewise_construct_t{}, l) {}
976QVariant::QVariant(QSize s) noexcept
977 : d(std::piecewise_construct_t{}, s) {}
978QVariant::QVariant(QSizeF s) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>)
979 : d(std::piecewise_construct_t{}, s) {}
980#endif
981#ifndef QT_BOOTSTRAPPED
982QVariant::QVariant(const QUrl &u) noexcept : d(std::piecewise_construct_t{}, u) {}
983#endif
984QVariant::QVariant(const QLocale &l) noexcept : d(std::piecewise_construct_t{}, l) {}
985#if QT_CONFIG(regularexpression)
986QVariant::QVariant(const QRegularExpression &re) noexcept : d(std::piecewise_construct_t{}, re) {}
987#endif // QT_CONFIG(regularexpression)
988QVariant::QVariant(QUuid uuid) noexcept(Private::FitsInInternalSize<16>) : d(std::piecewise_construct_t{}, uuid) {}
989#ifndef QT_BOOTSTRAPPED
990QVariant::QVariant(const QJsonValue &jsonValue) noexcept(Private::FitsInInternalSize<sizeof(CborValueStandIn)>)
991 : d(std::piecewise_construct_t{}, jsonValue)
992{ static_assert(sizeof(CborValueStandIn) == sizeof(QJsonValue)); }
993QVariant::QVariant(const QJsonObject &jsonObject) noexcept : d(std::piecewise_construct_t{}, jsonObject) {}
994QVariant::QVariant(const QJsonArray &jsonArray) noexcept : d(std::piecewise_construct_t{}, jsonArray) {}
995QVariant::QVariant(const QJsonDocument &jsonDocument) : d(std::piecewise_construct_t{}, jsonDocument) {}
996#endif // QT_BOOTSTRAPPED
997#if QT_CONFIG(itemmodel)
998QVariant::QVariant(const QModelIndex &modelIndex) noexcept(Private::FitsInInternalSize<8 + 2 * sizeof(quintptr)>)
999 : d(std::piecewise_construct_t{}, modelIndex) {}
1000QVariant::QVariant(const QPersistentModelIndex &modelIndex) : d(std::piecewise_construct_t{}, modelIndex) {}
1001#endif
1002
1003/*! \fn QVariant::Type QVariant::type() const
1004 \deprecated [6.0] Use typeId() or metaType() instead.
1005
1006 Returns the storage type of the value stored in the variant.
1007 Although this function is declared as returning QVariant::Type,
1008 the return value should be interpreted as QMetaType::Type. In
1009 particular, QVariant::UserType is returned here only if the value
1010 is equal or greater than QMetaType::User.
1011
1012 Note that return values in the ranges QVariant::Char through
1013 QVariant::RegExp and QVariant::Font through QVariant::Transform
1014 correspond to the values in the ranges QMetaType::QChar through
1015 QMetaType::QRegularExpression and QMetaType::QFont through QMetaType::QQuaternion.
1016
1017 Pay particular attention when working with char and QChar
1018 variants. Note that there is no QVariant constructor specifically
1019 for type char, but there is one for QChar. For a variant of type
1020 QChar, this function returns QVariant::Char, which is the same as
1021 QMetaType::QChar, but for a variant of type \c char, this function
1022 returns QMetaType::Char, which is \e not the same as
1023 QVariant::Char.
1024
1025 Also note that the types \c void*, \c long, \c short, \c unsigned
1026 \c long, \c unsigned \c short, \c unsigned \c char, \c float, \c
1027 QObject*, and \c QWidget* are represented in QMetaType::Type but
1028 not in QVariant::Type, and they can be returned by this function.
1029 However, they are considered to be user defined types when tested
1030 against QVariant::Type.
1031
1032 To test whether an instance of QVariant contains a data type that
1033 is compatible with the data type you are interested in, use
1034 canConvert().
1035
1036 \sa userType(), metaType()
1037*/
1038
1039/*! \fn int QVariant::userType() const
1040 \fn int QVariant::typeId() const
1041
1042 Returns the storage type of the value stored in the variant. This is
1043 the same as metaType().id().
1044
1045 \sa metaType()
1046*/
1047
1048/*!
1049 \since 6.0
1050
1051 Returns the QMetaType of the value stored in the variant.
1052*/
1053QMetaType QVariant::metaType() const
1054{
1055 return d.type();
1056}
1057
1058/*!
1059 Assigns the value of the variant \a variant to this variant.
1060*/
1061QVariant &QVariant::operator=(const QVariant &variant)
1062{
1063 if (this == &variant)
1064 return *this;
1065
1066 clear();
1067 d = clonePrivate(other: variant.d);
1068 return *this;
1069}
1070
1071/*!
1072 \fn void QVariant::swap(QVariant &other)
1073 \since 4.8
1074
1075 Swaps variant \a other with this variant. This operation is very
1076 fast and never fails.
1077*/
1078
1079/*!
1080 \fn void QVariant::detach()
1081
1082 \internal
1083*/
1084
1085void QVariant::detach()
1086{
1087 if (!d.is_shared || d.data.shared->ref.loadRelaxed() == 1)
1088 return;
1089
1090 Q_ASSERT(isValidMetaTypeForVariant(d.typeInterface(), constData()));
1091 Private dd(d.typeInterface());
1092 // null variant is never shared; anything else is NonNull
1093 customConstruct<UseCopy, NonNull>(iface: d.typeInterface(), d: &dd, copy: constData());
1094 if (!d.data.shared->ref.deref())
1095 customClear(d: &d);
1096 d.data.shared = dd.data.shared;
1097}
1098
1099/*!
1100 \fn bool QVariant::isDetached() const
1101
1102 \internal
1103*/
1104
1105/*!
1106 Returns the name of the type stored in the variant. The returned
1107 strings describe the C++ datatype used to store the data: for
1108 example, "QFont", "QString", or "QVariantList". An Invalid
1109 variant returns 0.
1110*/
1111const char *QVariant::typeName() const
1112{
1113 return d.type().name();
1114}
1115
1116/*!
1117 Convert this variant to type QMetaType::UnknownType and free up any resources
1118 used.
1119*/
1120void QVariant::clear()
1121{
1122 if (!d.is_shared || !d.data.shared->ref.deref())
1123 customClear(d: &d);
1124 d = {};
1125}
1126
1127/*!
1128 \fn const char *QVariant::typeToName(int typeId)
1129 \deprecated [6.0] Use \c QMetaType(typeId).name() instead.
1130
1131 Converts the int representation of the storage type, \a typeId, to
1132 its string representation.
1133
1134 Returns \nullptr if the type is QMetaType::UnknownType or doesn't exist.
1135*/
1136
1137/*!
1138 \fn QVariant::Type QVariant::nameToType(const char *name)
1139 \deprecated [6.0] Use \c QMetaType::fromName(name).id() instead
1140
1141 Converts the string representation of the storage type given in \a
1142 name, to its enum representation.
1143
1144 If the string representation cannot be converted to any enum
1145 representation, the variant is set to \c Invalid.
1146*/
1147
1148#ifndef QT_NO_DATASTREAM
1149enum { MapFromThreeCount = 36 };
1150static const ushort mapIdFromQt3ToCurrent[MapFromThreeCount] =
1151{
1152 QMetaType::UnknownType,
1153 QMetaType::QVariantMap,
1154 QMetaType::QVariantList,
1155 QMetaType::QString,
1156 QMetaType::QStringList,
1157 QMetaType::QFont,
1158 QMetaType::QPixmap,
1159 QMetaType::QBrush,
1160 QMetaType::QRect,
1161 QMetaType::QSize,
1162 QMetaType::QColor,
1163 QMetaType::QPalette,
1164 0, // ColorGroup
1165 QMetaType::QIcon,
1166 QMetaType::QPoint,
1167 QMetaType::QImage,
1168 QMetaType::Int,
1169 QMetaType::UInt,
1170 QMetaType::Bool,
1171 QMetaType::Double,
1172 0, // Buggy ByteArray, QByteArray never had id == 20
1173 QMetaType::QPolygon,
1174 QMetaType::QRegion,
1175 QMetaType::QBitmap,
1176 QMetaType::QCursor,
1177 QMetaType::QSizePolicy,
1178 QMetaType::QDate,
1179 QMetaType::QTime,
1180 QMetaType::QDateTime,
1181 QMetaType::QByteArray,
1182 QMetaType::QBitArray,
1183#if QT_CONFIG(shortcut)
1184 QMetaType::QKeySequence,
1185#else
1186 0, // QKeySequence
1187#endif
1188 QMetaType::QPen,
1189 QMetaType::LongLong,
1190 QMetaType::ULongLong,
1191#if QT_CONFIG(easingcurve)
1192 QMetaType::QEasingCurve
1193#endif
1194};
1195
1196// values needed to map Qt5 based type id's to Qt6 based ones
1197constexpr int Qt5UserType = 1024;
1198constexpr int Qt5LastCoreType = QMetaType::QCborMap;
1199constexpr int Qt5FirstGuiType = 64;
1200constexpr int Qt5LastGuiType = 87;
1201constexpr int Qt5SizePolicy = 121;
1202constexpr int Qt5RegExp = 27;
1203constexpr int Qt5KeySequence = 75;
1204constexpr int Qt5QQuaternion = 85;
1205
1206constexpr int Qt6ToQt5GuiTypeDelta = qToUnderlying(e: QMetaType::FirstGuiType) - Qt5FirstGuiType;
1207
1208/*!
1209 Internal function for loading a variant from stream \a s. Use the
1210 stream operators instead.
1211
1212 \internal
1213*/
1214void QVariant::load(QDataStream &s)
1215{
1216 clear();
1217
1218 quint32 typeId;
1219 s >> typeId;
1220 if (s.version() < QDataStream::Qt_4_0) {
1221 // map to Qt 5 ids
1222 if (typeId >= MapFromThreeCount)
1223 return;
1224 typeId = mapIdFromQt3ToCurrent[typeId];
1225 } else if (s.version() < QDataStream::Qt_5_0) {
1226 // map to Qt 5 type ids
1227 if (typeId == 127 /* QVariant::UserType */) {
1228 typeId = Qt5UserType;
1229 } else if (typeId >= 128 && typeId != Qt5UserType) {
1230 // In Qt4 id == 128 was FirstExtCoreType. In Qt5 ExtCoreTypes set was merged to CoreTypes
1231 // by moving all ids down by 97.
1232 typeId -= 97;
1233 } else if (typeId == 75 /* QSizePolicy */) {
1234 typeId = Qt5SizePolicy;
1235 } else if (typeId > 75 && typeId <= 86) {
1236 // and as a result these types received lower ids too
1237 // QKeySequence QPen QTextLength QTextFormat QTransform QMatrix4x4 QVector2D QVector3D QVector4D QQuaternion
1238 typeId -=1;
1239 }
1240 }
1241 if (s.version() < QDataStream::Qt_6_0) {
1242 // map from Qt 5 to Qt 6 values
1243 if (typeId == Qt5UserType) {
1244 typeId = QMetaType::User;
1245 } else if (typeId >= Qt5FirstGuiType && typeId <= Qt5LastGuiType) {
1246 typeId += Qt6ToQt5GuiTypeDelta;
1247 } else if (typeId == Qt5SizePolicy) {
1248 typeId = QMetaType::QSizePolicy;
1249 } else if (typeId == Qt5RegExp) {
1250 typeId = QMetaType::fromName(name: "QRegExp").id();
1251 }
1252 }
1253
1254 qint8 is_null = false;
1255 if (s.version() >= QDataStream::Qt_4_2)
1256 s >> is_null;
1257 if (typeId == QMetaType::User) {
1258 QByteArray name;
1259 s >> name;
1260 typeId = QMetaType::fromName(name).id();
1261 if (typeId == QMetaType::UnknownType) {
1262 s.setStatus(QDataStream::ReadCorruptData);
1263 qWarning(msg: "QVariant::load: unknown user type with name %s.", name.constData());
1264 return;
1265 }
1266 }
1267 create(type: typeId, copy: nullptr);
1268 d.is_null = is_null;
1269
1270 if (!isValid()) {
1271 if (s.version() < QDataStream::Qt_5_0) {
1272 // Since we wrote something, we should read something
1273 QString x;
1274 s >> x;
1275 }
1276 d.is_null = true;
1277 return;
1278 }
1279
1280 // const cast is safe since we operate on a newly constructed variant
1281 void *data = const_cast<void *>(constData());
1282 if (!d.type().load(stream&: s, data)) {
1283 s.setStatus(QDataStream::ReadCorruptData);
1284 qWarning(msg: "QVariant::load: unable to load type %d.", d.type().id());
1285 }
1286}
1287
1288/*!
1289 Internal function for saving a variant to the stream \a s. Use the
1290 stream operators instead.
1291
1292 \internal
1293*/
1294void QVariant::save(QDataStream &s) const
1295{
1296 quint32 typeId = d.type().id();
1297 bool saveAsUserType = false;
1298 if (typeId >= QMetaType::User) {
1299 typeId = QMetaType::User;
1300 saveAsUserType = true;
1301 }
1302 if (s.version() < QDataStream::Qt_6_0) {
1303 // map to Qt 5 values
1304 if (typeId == QMetaType::User) {
1305 typeId = Qt5UserType;
1306 if (!strcmp(s1: d.type().name(), s2: "QRegExp")) {
1307 typeId = 27; // QRegExp in Qt 4/5
1308 }
1309 } else if (typeId > Qt5LastCoreType && typeId <= QMetaType::LastCoreType) {
1310 // the type didn't exist in Qt 5
1311 typeId = Qt5UserType;
1312 saveAsUserType = true;
1313 } else if (typeId >= QMetaType::FirstGuiType && typeId <= QMetaType::LastGuiType) {
1314 typeId -= Qt6ToQt5GuiTypeDelta;
1315 if (typeId > Qt5LastGuiType) {
1316 typeId = Qt5UserType;
1317 saveAsUserType = true;
1318 }
1319 } else if (typeId == QMetaType::QSizePolicy) {
1320 typeId = Qt5SizePolicy;
1321 }
1322 }
1323 if (s.version() < QDataStream::Qt_4_0) {
1324 int i;
1325 for (i = 0; i <= MapFromThreeCount - 1; ++i) {
1326 if (mapIdFromQt3ToCurrent[i] == typeId) {
1327 typeId = i;
1328 break;
1329 }
1330 }
1331 if (i >= MapFromThreeCount) {
1332 s << QVariant();
1333 return;
1334 }
1335 } else if (s.version() < QDataStream::Qt_5_0) {
1336 if (typeId == Qt5UserType) {
1337 typeId = 127; // QVariant::UserType had this value in Qt4
1338 saveAsUserType = true;
1339 } else if (typeId >= 128 - 97 && typeId <= Qt5LastCoreType) {
1340 // In Qt4 id == 128 was FirstExtCoreType. In Qt5 ExtCoreTypes set was merged to CoreTypes
1341 // by moving all ids down by 97.
1342 typeId += 97;
1343 } else if (typeId == Qt5SizePolicy) {
1344 typeId = 75;
1345 } else if (typeId >= Qt5KeySequence && typeId <= Qt5QQuaternion) {
1346 // and as a result these types received lower ids too
1347 typeId += 1;
1348 } else if (typeId > Qt5QQuaternion || typeId == QMetaType::QUuid) {
1349 // These existed in Qt 4 only as a custom type
1350 typeId = 127;
1351 saveAsUserType = true;
1352 }
1353 }
1354 const char *typeName = nullptr;
1355 if (saveAsUserType) {
1356 if (s.version() < QDataStream::Qt_6_0)
1357 typeName = QtMetaTypePrivate::typedefNameForType(type_d: d.type().d_ptr);
1358 if (!typeName)
1359 typeName = d.type().name();
1360 }
1361 s << typeId;
1362 if (s.version() >= QDataStream::Qt_4_2)
1363 s << qint8(d.is_null);
1364 if (typeName)
1365 s << typeName;
1366
1367 if (!isValid()) {
1368 if (s.version() < QDataStream::Qt_5_0)
1369 s << QString();
1370 return;
1371 }
1372
1373 if (!d.type().save(stream&: s, data: constData())) {
1374 qWarning(msg: "QVariant::save: unable to save type '%s' (type id: %d).\n",
1375 d.type().name(), d.type().id());
1376 Q_ASSERT_X(false, "QVariant::save", "Invalid type to save");
1377 }
1378}
1379
1380/*!
1381 \since 4.4
1382 \relates QVariant
1383
1384 Reads a variant \a p from the stream \a s.
1385
1386 \note If the stream contains types that aren't the built-in ones (see \l
1387 QMetaType::Type), those types must be registered using qRegisterMetaType()
1388 or QMetaType::registerType() before the variant can be properly loaded. If
1389 an unregistered type is found, QVariant will set the corrupt flag in the
1390 stream, stop processing and print a warning. For example, for QList<int>
1391 it would print the following:
1392
1393 \quotation
1394 QVariant::load: unknown user type with name QList<int>
1395 \endquotation
1396
1397 \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
1398*/
1399QDataStream &operator>>(QDataStream &s, QVariant &p)
1400{
1401 p.load(s);
1402 return s;
1403}
1404
1405/*!
1406 Writes a variant \a p to the stream \a s.
1407 \relates QVariant
1408
1409 \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
1410*/
1411QDataStream &operator<<(QDataStream &s, const QVariant &p)
1412{
1413 p.save(s);
1414 return s;
1415}
1416
1417/*! \fn QDataStream& operator>>(QDataStream &s, QVariant::Type &p)
1418 \relates QVariant
1419 \deprecated [6.0] Stream QMetaType::Type instead.
1420
1421 Reads a variant type \a p in enum representation from the stream \a s.
1422*/
1423
1424/*! \fn QDataStream& operator<<(QDataStream &s, const QVariant::Type p)
1425 \relates QVariant
1426 \deprecated [6.0] Stream QMetaType::Type instead.
1427
1428 Writes a variant type \a p to the stream \a s.
1429*/
1430#endif //QT_NO_DATASTREAM
1431
1432/*!
1433 \fn bool QVariant::isValid() const
1434
1435 Returns \c true if the storage type of this variant is not
1436 QMetaType::UnknownType; otherwise returns \c false.
1437*/
1438
1439/*!
1440 \fn QStringList QVariant::toStringList() const
1441
1442 Returns the variant as a QStringList if the variant has userType()
1443 \l QMetaType::QStringList, \l QMetaType::QString, or
1444 \l QMetaType::QVariantList of a type that can be converted to QString;
1445 otherwise returns an empty list.
1446
1447 \sa canConvert(), convert()
1448*/
1449QStringList QVariant::toStringList() const
1450{
1451 return qvariant_cast<QStringList>(v: *this);
1452}
1453
1454/*!
1455 Returns the variant as a QString if the variant has a userType()
1456 including, but not limited to:
1457
1458 \l QMetaType::QString, \l QMetaType::Bool, \l QMetaType::QByteArray,
1459 \l QMetaType::QChar, \l QMetaType::QDate, \l QMetaType::QDateTime,
1460 \l QMetaType::Double, \l QMetaType::Int, \l QMetaType::LongLong,
1461 \l QMetaType::QStringList, \l QMetaType::QTime, \l QMetaType::UInt, or
1462 \l QMetaType::ULongLong.
1463
1464 Calling QVariant::toString() on an unsupported variant returns an empty
1465 string.
1466
1467 \sa canConvert(), convert()
1468*/
1469QString QVariant::toString() const
1470{
1471 return qvariant_cast<QString>(v: *this);
1472}
1473
1474/*!
1475 Returns the variant as a QVariantMap if the variant has type() \l
1476 QMetaType::QVariantMap. If it doesn't, QVariant will attempt to
1477 convert the type to a map and then return it. This will succeed for
1478 any type that has registered a converter to QVariantMap or which was
1479 declared as a associative container using
1480 \l{Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE}. If none of those
1481 conditions are true, this function will return an empty map.
1482
1483 \sa canConvert(), convert()
1484*/
1485QVariantMap QVariant::toMap() const
1486{
1487 return qvariant_cast<QVariantMap>(v: *this);
1488}
1489
1490/*!
1491 Returns the variant as a QHash<QString, QVariant> if the variant
1492 has type() \l QMetaType::QVariantHash; otherwise returns an empty map.
1493
1494 \sa canConvert(), convert()
1495*/
1496QVariantHash QVariant::toHash() const
1497{
1498 return qvariant_cast<QVariantHash>(v: *this);
1499}
1500
1501/*!
1502 \fn QDate QVariant::toDate() const
1503
1504 Returns the variant as a QDate if the variant has userType()
1505 \l QMetaType::QDate, \l QMetaType::QDateTime, or \l QMetaType::QString;
1506 otherwise returns an invalid date.
1507
1508 If the type() is \l QMetaType::QString, an invalid date will be returned if
1509 the string cannot be parsed as a Qt::ISODate format date.
1510
1511 \sa canConvert(), convert()
1512*/
1513QDate QVariant::toDate() const
1514{
1515 return qvariant_cast<QDate>(v: *this);
1516}
1517
1518/*!
1519 \fn QTime QVariant::toTime() const
1520
1521 Returns the variant as a QTime if the variant has userType()
1522 \l QMetaType::QTime, \l QMetaType::QDateTime, or \l QMetaType::QString;
1523 otherwise returns an invalid time.
1524
1525 If the type() is \l QMetaType::QString, an invalid time will be returned if
1526 the string cannot be parsed as a Qt::ISODate format time.
1527
1528 \sa canConvert(), convert()
1529*/
1530QTime QVariant::toTime() const
1531{
1532 return qvariant_cast<QTime>(v: *this);
1533}
1534
1535/*!
1536 \fn QDateTime QVariant::toDateTime() const
1537
1538 Returns the variant as a QDateTime if the variant has userType()
1539 \l QMetaType::QDateTime, \l QMetaType::QDate, or \l QMetaType::QString;
1540 otherwise returns an invalid date/time.
1541
1542 If the type() is \l QMetaType::QString, an invalid date/time will be
1543 returned if the string cannot be parsed as a Qt::ISODate format date/time.
1544
1545 \sa canConvert(), convert()
1546*/
1547QDateTime QVariant::toDateTime() const
1548{
1549 return qvariant_cast<QDateTime>(v: *this);
1550}
1551
1552/*!
1553 \since 4.7
1554 \fn QEasingCurve QVariant::toEasingCurve() const
1555
1556 Returns the variant as a QEasingCurve if the variant has userType()
1557 \l QMetaType::QEasingCurve; otherwise returns a default easing curve.
1558
1559 \sa canConvert(), convert()
1560*/
1561#if QT_CONFIG(easingcurve)
1562QEasingCurve QVariant::toEasingCurve() const
1563{
1564 return qvariant_cast<QEasingCurve>(v: *this);
1565}
1566#endif
1567
1568/*!
1569 \fn QByteArray QVariant::toByteArray() const
1570
1571 Returns the variant as a QByteArray if the variant has userType()
1572 \l QMetaType::QByteArray or \l QMetaType::QString (converted using
1573 QString::fromUtf8()); otherwise returns an empty byte array.
1574
1575 \sa canConvert(), convert()
1576*/
1577QByteArray QVariant::toByteArray() const
1578{
1579 return qvariant_cast<QByteArray>(v: *this);
1580}
1581
1582#ifndef QT_NO_GEOM_VARIANT
1583/*!
1584 \fn QPoint QVariant::toPoint() const
1585
1586 Returns the variant as a QPoint if the variant has userType()
1587 \l QMetaType::QPoint or \l QMetaType::QPointF; otherwise returns a null
1588 QPoint.
1589
1590 \sa canConvert(), convert()
1591*/
1592QPoint QVariant::toPoint() const
1593{
1594 return qvariant_cast<QPoint>(v: *this);
1595}
1596
1597/*!
1598 \fn QRect QVariant::toRect() const
1599
1600 Returns the variant as a QRect if the variant has userType()
1601 \l QMetaType::QRect; otherwise returns an invalid QRect.
1602
1603 \sa canConvert(), convert()
1604*/
1605QRect QVariant::toRect() const
1606{
1607 return qvariant_cast<QRect>(v: *this);
1608}
1609
1610/*!
1611 \fn QSize QVariant::toSize() const
1612
1613 Returns the variant as a QSize if the variant has userType()
1614 \l QMetaType::QSize; otherwise returns an invalid QSize.
1615
1616 \sa canConvert(), convert()
1617*/
1618QSize QVariant::toSize() const
1619{
1620 return qvariant_cast<QSize>(v: *this);
1621}
1622
1623/*!
1624 \fn QSizeF QVariant::toSizeF() const
1625
1626 Returns the variant as a QSizeF if the variant has userType() \l
1627 QMetaType::QSizeF; otherwise returns an invalid QSizeF.
1628
1629 \sa canConvert(), convert()
1630*/
1631QSizeF QVariant::toSizeF() const
1632{
1633 return qvariant_cast<QSizeF>(v: *this);
1634}
1635
1636/*!
1637 \fn QRectF QVariant::toRectF() const
1638
1639 Returns the variant as a QRectF if the variant has userType()
1640 \l QMetaType::QRect or \l QMetaType::QRectF; otherwise returns an invalid
1641 QRectF.
1642
1643 \sa canConvert(), convert()
1644*/
1645QRectF QVariant::toRectF() const
1646{
1647 return qvariant_cast<QRectF>(v: *this);
1648}
1649
1650/*!
1651 \fn QLineF QVariant::toLineF() const
1652
1653 Returns the variant as a QLineF if the variant has userType()
1654 \l QMetaType::QLineF; otherwise returns an invalid QLineF.
1655
1656 \sa canConvert(), convert()
1657*/
1658QLineF QVariant::toLineF() const
1659{
1660 return qvariant_cast<QLineF>(v: *this);
1661}
1662
1663/*!
1664 \fn QLine QVariant::toLine() const
1665
1666 Returns the variant as a QLine if the variant has userType()
1667 \l QMetaType::QLine; otherwise returns an invalid QLine.
1668
1669 \sa canConvert(), convert()
1670*/
1671QLine QVariant::toLine() const
1672{
1673 return qvariant_cast<QLine>(v: *this);
1674}
1675
1676/*!
1677 \fn QPointF QVariant::toPointF() const
1678
1679 Returns the variant as a QPointF if the variant has userType() \l
1680 QMetaType::QPoint or \l QMetaType::QPointF; otherwise returns a null
1681 QPointF.
1682
1683 \sa canConvert(), convert()
1684*/
1685QPointF QVariant::toPointF() const
1686{
1687 return qvariant_cast<QPointF>(v: *this);
1688}
1689
1690#endif // QT_NO_GEOM_VARIANT
1691
1692#ifndef QT_BOOTSTRAPPED
1693/*!
1694 \fn QUrl QVariant::toUrl() const
1695
1696 Returns the variant as a QUrl if the variant has userType()
1697 \l QMetaType::QUrl; otherwise returns an invalid QUrl.
1698
1699 \sa canConvert(), convert()
1700*/
1701QUrl QVariant::toUrl() const
1702{
1703 return qvariant_cast<QUrl>(v: *this);
1704}
1705#endif
1706
1707/*!
1708 \fn QLocale QVariant::toLocale() const
1709
1710 Returns the variant as a QLocale if the variant has userType()
1711 \l QMetaType::QLocale; otherwise returns an invalid QLocale.
1712
1713 \sa canConvert(), convert()
1714*/
1715QLocale QVariant::toLocale() const
1716{
1717 return qvariant_cast<QLocale>(v: *this);
1718}
1719
1720#if QT_CONFIG(regularexpression)
1721/*!
1722 \fn QRegularExpression QVariant::toRegularExpression() const
1723 \since 5.0
1724
1725 Returns the variant as a QRegularExpression if the variant has userType() \l
1726 QRegularExpression; otherwise returns an empty QRegularExpression.
1727
1728 \sa canConvert(), convert()
1729*/
1730QRegularExpression QVariant::toRegularExpression() const
1731{
1732 return qvariant_cast<QRegularExpression>(v: *this);
1733}
1734#endif // QT_CONFIG(regularexpression)
1735
1736#if QT_CONFIG(itemmodel)
1737/*!
1738 \since 5.0
1739
1740 Returns the variant as a QModelIndex if the variant has userType() \l
1741 QModelIndex; otherwise returns a default constructed QModelIndex.
1742
1743 \sa canConvert(), convert(), toPersistentModelIndex()
1744*/
1745QModelIndex QVariant::toModelIndex() const
1746{
1747 return qvariant_cast<QModelIndex>(v: *this);
1748}
1749
1750/*!
1751 \since 5.5
1752
1753 Returns the variant as a QPersistentModelIndex if the variant has userType() \l
1754 QPersistentModelIndex; otherwise returns a default constructed QPersistentModelIndex.
1755
1756 \sa canConvert(), convert(), toModelIndex()
1757*/
1758QPersistentModelIndex QVariant::toPersistentModelIndex() const
1759{
1760 return qvariant_cast<QPersistentModelIndex>(v: *this);
1761}
1762#endif // QT_CONFIG(itemmodel)
1763
1764/*!
1765 \since 5.0
1766
1767 Returns the variant as a QUuid if the variant has type()
1768 \l QMetaType::QUuid, \l QMetaType::QByteArray or \l QMetaType::QString;
1769 otherwise returns a default-constructed QUuid.
1770
1771 \sa canConvert(), convert()
1772*/
1773QUuid QVariant::toUuid() const
1774{
1775 return qvariant_cast<QUuid>(v: *this);
1776}
1777
1778#ifndef QT_BOOTSTRAPPED
1779/*!
1780 \since 5.0
1781
1782 Returns the variant as a QJsonValue if the variant has userType() \l
1783 QJsonValue; otherwise returns a default constructed QJsonValue.
1784
1785 \sa canConvert(), convert()
1786*/
1787QJsonValue QVariant::toJsonValue() const
1788{
1789 return qvariant_cast<QJsonValue>(v: *this);
1790}
1791
1792/*!
1793 \since 5.0
1794
1795 Returns the variant as a QJsonObject if the variant has userType() \l
1796 QJsonObject; otherwise returns a default constructed QJsonObject.
1797
1798 \sa canConvert(), convert()
1799*/
1800QJsonObject QVariant::toJsonObject() const
1801{
1802 return qvariant_cast<QJsonObject>(v: *this);
1803}
1804
1805/*!
1806 \since 5.0
1807
1808 Returns the variant as a QJsonArray if the variant has userType() \l
1809 QJsonArray; otherwise returns a default constructed QJsonArray.
1810
1811 \sa canConvert(), convert()
1812*/
1813QJsonArray QVariant::toJsonArray() const
1814{
1815 return qvariant_cast<QJsonArray>(v: *this);
1816}
1817
1818/*!
1819 \since 5.0
1820
1821 Returns the variant as a QJsonDocument if the variant has userType() \l
1822 QJsonDocument; otherwise returns a default constructed QJsonDocument.
1823
1824 \sa canConvert(), convert()
1825*/
1826QJsonDocument QVariant::toJsonDocument() const
1827{
1828 return qvariant_cast<QJsonDocument>(v: *this);
1829}
1830#endif // QT_BOOTSTRAPPED
1831
1832/*!
1833 \fn QChar QVariant::toChar() const
1834
1835 Returns the variant as a QChar if the variant has userType()
1836 \l QMetaType::QChar, \l QMetaType::Int, or \l QMetaType::UInt; otherwise
1837 returns an invalid QChar.
1838
1839 \sa canConvert(), convert()
1840*/
1841QChar QVariant::toChar() const
1842{
1843 return qvariant_cast<QChar>(v: *this);
1844}
1845
1846/*!
1847 Returns the variant as a QBitArray if the variant has userType()
1848 \l QMetaType::QBitArray; otherwise returns an empty bit array.
1849
1850 \sa canConvert(), convert()
1851*/
1852QBitArray QVariant::toBitArray() const
1853{
1854 return qvariant_cast<QBitArray>(v: *this);
1855}
1856
1857template <typename T>
1858inline T qNumVariantToHelper(const QVariant::Private &d, bool *ok)
1859{
1860 QMetaType t = QMetaType::fromType<T>();
1861 if (ok)
1862 *ok = true;
1863
1864 if (d.type() == t)
1865 return d.get<T>();
1866
1867 T ret = 0;
1868 bool success = QMetaType::convert(d.type(), d.storage(), t, &ret);
1869 if (ok)
1870 *ok = success;
1871 return ret;
1872}
1873
1874/*!
1875 Returns the variant as an int if the variant has userType()
1876 \l QMetaType::Int, \l QMetaType::Bool, \l QMetaType::QByteArray,
1877 \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::LongLong,
1878 \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong;
1879 otherwise returns 0.
1880
1881 If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
1882 converted to an int; otherwise \c{*}\a{ok} is set to false.
1883
1884 \b{Warning:} If the value is convertible to a \l QMetaType::LongLong but is
1885 too large to be represented in an int, the resulting arithmetic overflow
1886 will not be reflected in \a ok. A simple workaround is to use
1887 QString::toInt().
1888
1889 \sa canConvert(), convert()
1890*/
1891int QVariant::toInt(bool *ok) const
1892{
1893 return qNumVariantToHelper<int>(d, ok);
1894}
1895
1896/*!
1897 Returns the variant as an unsigned int if the variant has userType()
1898 \l QMetaType::UInt, \l QMetaType::Bool, \l QMetaType::QByteArray,
1899 \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int,
1900 \l QMetaType::LongLong, \l QMetaType::QString, or \l QMetaType::ULongLong;
1901 otherwise returns 0.
1902
1903 If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
1904 converted to an unsigned int; otherwise \c{*}\a{ok} is set to false.
1905
1906 \b{Warning:} If the value is convertible to a \l QMetaType::ULongLong but is
1907 too large to be represented in an unsigned int, the resulting arithmetic
1908 overflow will not be reflected in \a ok. A simple workaround is to use
1909 QString::toUInt().
1910
1911 \sa canConvert(), convert()
1912*/
1913uint QVariant::toUInt(bool *ok) const
1914{
1915 return qNumVariantToHelper<uint>(d, ok);
1916}
1917
1918/*!
1919 Returns the variant as a long long int if the variant has userType()
1920 \l QMetaType::LongLong, \l QMetaType::Bool, \l QMetaType::QByteArray,
1921 \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int,
1922 \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong;
1923 otherwise returns 0.
1924
1925 If \a ok is non-null: \c{*}\c{ok} is set to true if the value could be
1926 converted to an int; otherwise \c{*}\c{ok} is set to false.
1927
1928 \sa canConvert(), convert()
1929*/
1930qlonglong QVariant::toLongLong(bool *ok) const
1931{
1932 return qNumVariantToHelper<qlonglong>(d, ok);
1933}
1934
1935/*!
1936 Returns the variant as an unsigned long long int if the
1937 variant has type() \l QMetaType::ULongLong, \l QMetaType::Bool,
1938 \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::Double,
1939 \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString, or
1940 \l QMetaType::UInt; otherwise returns 0.
1941
1942 If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
1943 converted to an int; otherwise \c{*}\a{ok} is set to false.
1944
1945 \sa canConvert(), convert()
1946*/
1947qulonglong QVariant::toULongLong(bool *ok) const
1948{
1949 return qNumVariantToHelper<qulonglong>(d, ok);
1950}
1951
1952/*!
1953 Returns the variant as a bool if the variant has userType() Bool.
1954
1955 Returns \c true if the variant has userType() \l QMetaType::Bool,
1956 \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int,
1957 \l QMetaType::LongLong, \l QMetaType::UInt, or \l QMetaType::ULongLong and
1958 the value is non-zero, or if the variant has type \l QMetaType::QString or
1959 \l QMetaType::QByteArray and its lower-case content is not one of the
1960 following: empty, "0" or "false"; otherwise returns \c false.
1961
1962 \sa canConvert(), convert()
1963*/
1964bool QVariant::toBool() const
1965{
1966 auto boolType = QMetaType::fromType<bool>();
1967 if (d.type() == boolType)
1968 return d.get<bool>();
1969
1970 bool res = false;
1971 QMetaType::convert(fromType: d.type(), from: constData(), toType: boolType, to: &res);
1972 return res;
1973}
1974
1975/*!
1976 Returns the variant as a double if the variant has userType()
1977 \l QMetaType::Double, \l QMetaType::Float, \l QMetaType::Bool,
1978 \l QMetaType::QByteArray, \l QMetaType::Int, \l QMetaType::LongLong,
1979 \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong;
1980 otherwise returns 0.0.
1981
1982 If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
1983 converted to a double; otherwise \c{*}\a{ok} is set to false.
1984
1985 \sa canConvert(), convert()
1986*/
1987double QVariant::toDouble(bool *ok) const
1988{
1989 return qNumVariantToHelper<double>(d, ok);
1990}
1991
1992/*!
1993 Returns the variant as a float if the variant has userType()
1994 \l QMetaType::Double, \l QMetaType::Float, \l QMetaType::Bool,
1995 \l QMetaType::QByteArray, \l QMetaType::Int, \l QMetaType::LongLong,
1996 \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong;
1997 otherwise returns 0.0.
1998
1999 \since 4.6
2000
2001 If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
2002 converted to a double; otherwise \c{*}\a{ok} is set to false.
2003
2004 \sa canConvert(), convert()
2005*/
2006float QVariant::toFloat(bool *ok) const
2007{
2008 return qNumVariantToHelper<float>(d, ok);
2009}
2010
2011/*!
2012 Returns the variant as a qreal if the variant has userType()
2013 \l QMetaType::Double, \l QMetaType::Float, \l QMetaType::Bool,
2014 \l QMetaType::QByteArray, \l QMetaType::Int, \l QMetaType::LongLong,
2015 \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong;
2016 otherwise returns 0.0.
2017
2018 \since 4.6
2019
2020 If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
2021 converted to a double; otherwise \c{*}\a{ok} is set to false.
2022
2023 \sa canConvert(), convert()
2024*/
2025qreal QVariant::toReal(bool *ok) const
2026{
2027 return qNumVariantToHelper<qreal>(d, ok);
2028}
2029
2030/*!
2031 Returns the variant as a QVariantList if the variant has userType() \l
2032 QMetaType::QVariantList. If it doesn't, QVariant will attempt to convert
2033 the type to a list and then return it. This will succeed for any type that
2034 has registered a converter to QVariantList or which was declared as a
2035 sequential container using \l{Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE}. If
2036 none of those conditions are true, this function will return an empty
2037 list.
2038
2039 \sa canConvert(), convert()
2040*/
2041QVariantList QVariant::toList() const
2042{
2043 return qvariant_cast<QVariantList>(v: *this);
2044}
2045
2046/*!
2047 \fn bool QVariant::canConvert(int targetTypeId) const
2048 \overload
2049 \deprecated [6.0] Use \c canConvert(QMetaType(targetTypeId)) instead.
2050
2051 \sa QMetaType::canConvert()
2052*/
2053
2054/*!
2055 \fn bool QVariant::canConvert(QMetaType type) const
2056 \since 6.0
2057
2058 Returns \c true if the variant's type can be cast to the requested
2059 type, \a type. Such casting is done automatically when calling the
2060 toInt(), toBool(), ... methods.
2061
2062 \sa QMetaType::canConvert()
2063*/
2064
2065
2066/*!
2067 \fn bool QVariant::convert(int targetTypeId)
2068 \deprecated [6.0] Use \c convert(QMetaType(targetTypeId)) instead.
2069
2070 Casts the variant to the requested type, \a targetTypeId. If the cast cannot be
2071 done, the variant is still changed to the requested type, but is left in a cleared
2072 null state similar to that constructed by QVariant(Type).
2073
2074 Returns \c true if the current type of the variant was successfully cast;
2075 otherwise returns \c false.
2076
2077 A QVariant containing a pointer to a type derived from QObject will also convert
2078 and return true for this function if a qobject_cast to the type described
2079 by \a targetTypeId would succeed. Note that this only works for QObject subclasses
2080 which use the Q_OBJECT macro.
2081
2082 \note converting QVariants that are null due to not being initialized or having
2083 failed a previous conversion will always fail, changing the type, remaining null,
2084 and returning \c false.
2085
2086 \sa canConvert(), clear()
2087*/
2088
2089/*!
2090 Casts the variant to the requested type, \a targetType. If the cast cannot be
2091 done, the variant is still changed to the requested type, but is left in a cleared
2092 null state similar to that constructed by QVariant(Type).
2093
2094 Returns \c true if the current type of the variant was successfully cast;
2095 otherwise returns \c false.
2096
2097 A QVariant containing a pointer to a type derived from QObject will also convert
2098 and return true for this function if a qobject_cast to the type described
2099 by \a targetType would succeed. Note that this only works for QObject subclasses
2100 which use the Q_OBJECT macro.
2101
2102 \note converting QVariants that are null due to not being initialized or having
2103 failed a previous conversion will always fail, changing the type, remaining null,
2104 and returning \c false.
2105
2106 \since 6.0
2107
2108 \sa canConvert(), clear()
2109*/
2110
2111bool QVariant::convert(QMetaType targetType)
2112{
2113 if (d.type() == targetType)
2114 return targetType.isValid();
2115
2116 QVariant oldValue = *this;
2117
2118 clear();
2119 create(type: targetType, copy: nullptr);
2120 if (!oldValue.canConvert(targetType))
2121 return false;
2122
2123 // Fail if the value is not initialized or was forced null by a previous failed convert.
2124 if (oldValue.d.is_null && oldValue.d.type().id() != QMetaType::Nullptr)
2125 return false;
2126
2127 bool ok = QMetaType::convert(fromType: oldValue.d.type(), from: oldValue.constData(), toType: targetType, to: data());
2128 d.is_null = !ok;
2129 return ok;
2130}
2131
2132/*!
2133 \fn bool QVariant::convert(int type, void *ptr) const
2134 \internal
2135 Created for qvariant_cast() usage
2136*/
2137bool QVariant::convert(int type, void *ptr) const
2138{
2139 return QMetaType::convert(fromType: d.type(), from: constData(), toType: QMetaType(type), to: ptr);
2140}
2141
2142/*!
2143 \internal
2144*/
2145bool QVariant::view(int type, void *ptr)
2146{
2147 return QMetaType::view(fromType: d.type(), from: data(), toType: QMetaType(type), to: ptr);
2148}
2149
2150/*!
2151 \fn bool QVariant::operator==(const QVariant &v1, const QVariant &v2)
2152
2153 Returns \c true if \a v1 and \a v2 are equal; otherwise returns \c false.
2154
2155 QVariant uses the equality operator of the type() contained to check for
2156 equality.
2157
2158 Variants of different types will always compare as not equal with a few
2159 exceptions:
2160
2161 \list
2162 \li If both types are numeric types (integers and floatins point numbers)
2163 Qt will compare those types using standard C++ type promotion rules.
2164 \li If one type is numeric and the other one a QString, Qt will try to
2165 convert the QString to a matching numeric type and if successful compare
2166 those.
2167 \li If both variants contain pointers to QObject derived types, QVariant
2168 will check whether the types are related and point to the same object.
2169 \endlist
2170
2171 The result of the function is not affected by the result of QVariant::isNull,
2172 which means that two values can be equal even if one of them is null and
2173 another is not.
2174*/
2175
2176/*!
2177 \fn bool QVariant::operator!=(const QVariant &v1, const QVariant &v2)
2178
2179 Returns \c false if \a v1 and \a v2 are equal; otherwise returns \c true.
2180
2181 QVariant uses the equality operator of the type() contained to check for
2182 equality.
2183
2184 Variants of different types will always compare as not equal with a few
2185 exceptions:
2186
2187 \list
2188 \li If both types are numeric types (integers and floatins point numbers)
2189 Qt will compare those types using standard C++ type promotion rules.
2190 \li If one type is numeric and the other one a QString, Qt will try to
2191 convert the QString to a matching numeric type and if successful compare
2192 those.
2193 \li If both variants contain pointers to QObject derived types, QVariant
2194 will check whether the types are related and point to the same object.
2195 \endlist
2196*/
2197
2198static bool qIsNumericType(uint tp)
2199{
2200 static const qulonglong numericTypeBits =
2201 Q_UINT64_C(1) << QMetaType::QString |
2202 Q_UINT64_C(1) << QMetaType::Bool |
2203 Q_UINT64_C(1) << QMetaType::Double |
2204 Q_UINT64_C(1) << QMetaType::Float |
2205 Q_UINT64_C(1) << QMetaType::Char |
2206 Q_UINT64_C(1) << QMetaType::Char16 |
2207 Q_UINT64_C(1) << QMetaType::Char32 |
2208 Q_UINT64_C(1) << QMetaType::SChar |
2209 Q_UINT64_C(1) << QMetaType::UChar |
2210 Q_UINT64_C(1) << QMetaType::Short |
2211 Q_UINT64_C(1) << QMetaType::UShort |
2212 Q_UINT64_C(1) << QMetaType::Int |
2213 Q_UINT64_C(1) << QMetaType::UInt |
2214 Q_UINT64_C(1) << QMetaType::Long |
2215 Q_UINT64_C(1) << QMetaType::ULong |
2216 Q_UINT64_C(1) << QMetaType::LongLong |
2217 Q_UINT64_C(1) << QMetaType::ULongLong;
2218 return tp < (CHAR_BIT * sizeof numericTypeBits) ? numericTypeBits & (Q_UINT64_C(1) << tp) : false;
2219}
2220
2221static bool qIsFloatingPoint(uint tp)
2222{
2223 return tp == QMetaType::Double || tp == QMetaType::Float || tp == QMetaType::Float16;
2224}
2225
2226static bool canBeNumericallyCompared(const QtPrivate::QMetaTypeInterface *iface1,
2227 const QtPrivate::QMetaTypeInterface *iface2)
2228{
2229 if (!iface1 || !iface2)
2230 return false;
2231
2232 // We don't need QMetaType::id() here because the type Id is always stored
2233 // directly for all built-in types.
2234 bool isNumeric1 = qIsNumericType(tp: iface1->typeId);
2235 bool isNumeric2 = qIsNumericType(tp: iface2->typeId);
2236
2237 // if they're both numeric (or QString), then they can be compared
2238 if (isNumeric1 && isNumeric2)
2239 return true;
2240
2241 bool isEnum1 = iface1->flags & QMetaType::IsEnumeration;
2242 bool isEnum2 = iface2->flags & QMetaType::IsEnumeration;
2243
2244 // if both are enums, we can only compare if they are the same enum
2245 // (the language does allow comparing two different enum types, but that's
2246 // usually considered poor coding and produces a warning)
2247 if (isEnum1 && isEnum2)
2248 return QMetaType(iface1) == QMetaType(iface2);
2249
2250 // if one is an enum and the other is a numeric, we can compare too
2251 if (isEnum1 && isNumeric2)
2252 return true;
2253 if (isNumeric1 && isEnum2)
2254 return true;
2255
2256 // we need at least one enum and one numeric...
2257 return false;
2258}
2259
2260static int numericTypePromotion(const QtPrivate::QMetaTypeInterface *iface1,
2261 const QtPrivate::QMetaTypeInterface *iface2)
2262{
2263 Q_ASSERT(canBeNumericallyCompared(iface1, iface2));
2264
2265 // We don't need QMetaType::id() here because the type Id is always stored
2266 // directly for the types we're comparing against below.
2267 uint t1 = iface1->typeId;
2268 uint t2 = iface2->typeId;
2269
2270 if ((t1 == QMetaType::Bool && t2 == QMetaType::QString) ||
2271 (t2 == QMetaType::Bool && t1 == QMetaType::QString))
2272 return QMetaType::Bool;
2273
2274 // C++ integral ranks: (4.13 Integer conversion rank [conv.rank])
2275 // bool < signed char < short < int < long < long long
2276 // unsigneds have the same rank as their signed counterparts
2277 // C++ integral promotion rules (4.5 Integral Promotions [conv.prom])
2278 // - any type with rank less than int can be converted to int or unsigned int
2279 // 5 Expressions [expr] paragraph 9:
2280 // - if either operand is double, the other shall be converted to double
2281 // - " " float, " " " float
2282 // - if both operands have the same type, no further conversion is needed.
2283 // - if both are signed or if both are unsigned, convert to the one with highest rank
2284 // - if the unsigned has higher or same rank, convert the signed to the unsigned one
2285 // - if the signed can represent all values of the unsigned, convert to the signed
2286 // - otherwise, convert to the unsigned corresponding to the rank of the signed
2287
2288 // floating point: we deviate from the C++ standard by always using qreal
2289 if (qIsFloatingPoint(tp: t1) || qIsFloatingPoint(tp: t2))
2290 return QMetaType::QReal;
2291
2292 auto isUnsigned = [](uint tp) {
2293 // only types for which sizeof(T) >= sizeof(int); lesser ones promote to int
2294 return tp == QMetaType::ULongLong || tp == QMetaType::ULong ||
2295 tp == QMetaType::UInt || tp == QMetaType::Char32;
2296 };
2297 bool isUnsigned1 = isUnsigned(t1);
2298 bool isUnsigned2 = isUnsigned(t2);
2299
2300 // integral rules:
2301 // 1) if either type is a 64-bit unsigned, compare as 64-bit unsigned
2302 if (isUnsigned1 && iface1->size > sizeof(int))
2303 return QMetaType::ULongLong;
2304 if (isUnsigned2 && iface2->size > sizeof(int))
2305 return QMetaType::ULongLong;
2306
2307 // 2) if either type is 64-bit, compare as 64-bit signed
2308 if (iface1->size > sizeof(int) || iface2->size > sizeof(int))
2309 return QMetaType::LongLong;
2310
2311 // 3) if either type is 32-bit unsigned, compare as 32-bit unsigned
2312 if (isUnsigned1 || isUnsigned2)
2313 return QMetaType::UInt;
2314
2315 // 4) otherwise, just do int promotion
2316 return QMetaType::Int;
2317}
2318
2319template <typename Numeric> static QPartialOrdering spaceShip(Numeric lhs, Numeric rhs)
2320{
2321 if (lhs == rhs)
2322 return QPartialOrdering::Equivalent;
2323 if constexpr (std::numeric_limits<Numeric>::has_quiet_NaN) {
2324 if (std::isnan(lhs) || std::isnan(rhs))
2325 return QPartialOrdering::Unordered;
2326 }
2327
2328 bool smaller;
2329 if constexpr (std::is_same_v<Numeric, QObject *>)
2330 smaller = std::less<QObject *>()(lhs, rhs); // can't use less all the time because of bool
2331 else
2332 smaller = lhs < rhs;
2333 return smaller ? QPartialOrdering::Less : QPartialOrdering::Greater;
2334}
2335
2336static QPartialOrdering integralCompare(uint promotedType, const QVariant::Private *d1, const QVariant::Private *d2)
2337{
2338 // use toLongLong to retrieve the data, it gets us all the bits
2339 std::optional<qlonglong> l1 = qConvertToNumber(d: d1, allowStringToBool: promotedType == QMetaType::Bool);
2340 std::optional<qlonglong> l2 = qConvertToNumber(d: d2, allowStringToBool: promotedType == QMetaType::Bool);
2341 if (!l1 || !l2)
2342 return QPartialOrdering::Unordered;
2343 if (promotedType == QMetaType::UInt)
2344 return spaceShip<uint>(lhs: *l1, rhs: *l2);
2345 if (promotedType == QMetaType::LongLong)
2346 return spaceShip<qlonglong>(lhs: *l1, rhs: *l2);
2347 if (promotedType == QMetaType::ULongLong)
2348 return spaceShip<qulonglong>(lhs: *l1, rhs: *l2);
2349
2350 return spaceShip<int>(lhs: *l1, rhs: *l2);
2351}
2352
2353static QPartialOrdering numericCompare(const QVariant::Private *d1, const QVariant::Private *d2)
2354{
2355 uint promotedType = numericTypePromotion(iface1: d1->typeInterface(), iface2: d2->typeInterface());
2356 if (promotedType != QMetaType::QReal)
2357 return integralCompare(promotedType, d1, d2);
2358
2359 // floating point comparison
2360 const auto r1 = qConvertToRealNumber(d: d1);
2361 const auto r2 = qConvertToRealNumber(d: d2);
2362 if (!r1 || !r2)
2363 return QPartialOrdering::Unordered;
2364 if (*r1 == *r2)
2365 return QPartialOrdering::Equivalent;
2366
2367 return spaceShip(lhs: *r1, rhs: *r2);
2368}
2369
2370#ifndef QT_BOOTSTRAPPED
2371static bool qvCanConvertMetaObject(QMetaType fromType, QMetaType toType)
2372{
2373 if ((fromType.flags() & QMetaType::PointerToQObject)
2374 && (toType.flags() & QMetaType::PointerToQObject)) {
2375 const QMetaObject *f = fromType.metaObject();
2376 const QMetaObject *t = toType.metaObject();
2377 return f && t && (f->inherits(metaObject: t) || t->inherits(metaObject: f));
2378 }
2379 return false;
2380}
2381
2382static QPartialOrdering pointerCompare(const QVariant::Private *d1, const QVariant::Private *d2)
2383{
2384 return spaceShip<QObject *>(lhs: d1->get<QObject *>(), rhs: d2->get<QObject *>());
2385}
2386#endif
2387
2388/*!
2389 \internal
2390 */
2391bool QVariant::equals(const QVariant &v) const
2392{
2393 auto metatype = d.type();
2394
2395 if (metatype != v.metaType()) {
2396 // try numeric comparisons, with C++ type promotion rules (no conversion)
2397 if (canBeNumericallyCompared(iface1: metatype.iface(), iface2: v.d.type().iface()))
2398 return numericCompare(d1: &d, d2: &v.d) == QPartialOrdering::Equivalent;
2399#ifndef QT_BOOTSTRAPPED
2400 // if both types are related pointers to QObjects, check if they point to the same object
2401 if (qvCanConvertMetaObject(fromType: metatype, toType: v.metaType()))
2402 return pointerCompare(d1: &d, d2: &v.d) == QPartialOrdering::Equivalent;
2403#endif
2404 return false;
2405 }
2406
2407 // For historical reasons: QVariant() == QVariant()
2408 if (!metatype.isValid())
2409 return true;
2410
2411 return metatype.equals(lhs: d.storage(), rhs: v.d.storage());
2412}
2413
2414/*!
2415 Compares the objects at \a lhs and \a rhs for ordering.
2416
2417 Returns QPartialOrdering::Unordered if comparison is not supported
2418 or the values are unordered. Otherwise, returns
2419 QPartialOrdering::Less, QPartialOrdering::Equivalent or
2420 QPartialOrdering::Greater if \a lhs is less than, equivalent
2421 to or greater than \a rhs, respectively.
2422
2423 If the variants contain data with a different metatype, the values are considered
2424 unordered unless they are both of numeric or pointer types, where regular numeric or
2425 pointer comparison rules will be used.
2426 \note: If a numeric comparison is done and at least one value is NaN, QPartialOrdering::Unordered
2427 is returned.
2428
2429 If both variants contain data of the same metatype, the method will use the
2430 QMetaType::compare method to determine the ordering of the two variants, which can
2431 also indicate that it can't establish an ordering between the two values.
2432
2433 \since 6.0
2434 \sa QMetaType::compare(), QMetaType::isOrdered()
2435*/
2436QPartialOrdering QVariant::compare(const QVariant &lhs, const QVariant &rhs)
2437{
2438 QMetaType t = lhs.d.type();
2439 if (t != rhs.d.type()) {
2440 // try numeric comparisons, with C++ type promotion rules (no conversion)
2441 if (canBeNumericallyCompared(iface1: lhs.d.type().iface(), iface2: rhs.d.type().iface()))
2442 return numericCompare(d1: &lhs.d, d2: &rhs.d);
2443#ifndef QT_BOOTSTRAPPED
2444 if (qvCanConvertMetaObject(fromType: lhs.metaType(), toType: rhs.metaType()))
2445 return pointerCompare(d1: &lhs.d, d2: &rhs.d);
2446#endif
2447 return QPartialOrdering::Unordered;
2448 }
2449 return t.compare(lhs: lhs.constData(), rhs: rhs.constData());
2450}
2451
2452/*!
2453 \fn const void *QVariant::constData() const
2454 \fn const void* QVariant::data() const
2455
2456 Returns a pointer to the contained object as a generic void* that cannot be
2457 written to.
2458
2459 \sa get_if(), QMetaType
2460 */
2461
2462/*!
2463 Returns a pointer to the contained object as a generic void* that can be
2464 written to.
2465
2466 This function detaches the QVariant. When called on a \l{isNull}{null-QVariant},
2467 the QVariant will not be null after the call.
2468
2469 \sa get_if(), QMetaType
2470*/
2471void *QVariant::data()
2472{
2473 detach();
2474 // set is_null to false, as the caller is likely to write some data into this variant
2475 d.is_null = false;
2476 return const_cast<void *>(constData());
2477}
2478
2479/*!
2480 \since 6.6
2481 \fn template <typename T> const T* QVariant::get_if(const QVariant *v)
2482 \fn template <typename T> T* QVariant::get_if(QVariant *v)
2483
2484 If \a v contains an object of type \c T, returns a pointer to the contained
2485 object, otherwise returns \nullptr.
2486
2487 The overload taking a mutable \a v detaches \a v: When called on a
2488 \l{isNull()}{null} \a v with matching type \c T, \a v will not be null
2489 after the call.
2490
2491 These functions are provided for compatibility with \c{std::variant}.
2492
2493 \sa data()
2494*/
2495
2496/*!
2497 \since 6.6
2498 \fn template <typename T> T &QVariant::get(QVariant &v)
2499 \fn template <typename T> const T &QVariant::get(const QVariant &v)
2500 \fn template <typename T> T &&QVariant::get(QVariant &&v)
2501 \fn template <typename T> const T &&QVariant::get(const QVariant &&v)
2502
2503 If \a v contains an object of type \c T, returns a reference to the contained
2504 object, otherwise the call has undefined behavior.
2505
2506 The overloads taking a mutable \a v detach \a v: When called on a
2507 \l{isNull()}{null} \a v with matching type \c T, \a v will not be null
2508 after the call.
2509
2510 These functions are provided for compatibility with \c{std::variant}.
2511
2512 \sa get_if(), data()
2513*/
2514
2515/*!
2516 Returns \c true if this is a null variant, false otherwise.
2517
2518 A variant is considered null if it contains no initialized value or a null pointer.
2519
2520 \note This behavior has been changed from Qt 5, where isNull() would also
2521 return true if the variant contained an object of a builtin type with an isNull()
2522 method that returned true for that object.
2523
2524 \sa convert()
2525*/
2526bool QVariant::isNull() const
2527{
2528 if (d.is_null || !metaType().isValid())
2529 return true;
2530 if (metaType().flags() & QMetaType::IsPointer)
2531 return d.get<void *>() == nullptr;
2532 return false;
2533}
2534
2535#ifndef QT_NO_DEBUG_STREAM
2536QDebug QVariant::qdebugHelper(QDebug dbg) const
2537{
2538 QDebugStateSaver saver(dbg);
2539 const uint typeId = d.type().id();
2540 dbg.nospace() << "QVariant(";
2541 if (typeId != QMetaType::UnknownType) {
2542 dbg << d.type().name() << ", ";
2543 bool streamed = d.type().debugStream(dbg, rhs: d.storage());
2544 if (!streamed && canConvert<QString>())
2545 dbg << toString();
2546 } else {
2547 dbg << "Invalid";
2548 }
2549 dbg << ')';
2550 return dbg;
2551}
2552
2553QVariant QVariant::moveConstruct(QMetaType type, void *data)
2554{
2555 QVariant var;
2556 var.d = QVariant::Private(type.d_ptr);
2557 customConstruct<ForceMove, NonNull>(iface: type.d_ptr, d: &var.d, copy: data);
2558 return var;
2559}
2560
2561QVariant QVariant::copyConstruct(QMetaType type, const void *data)
2562{
2563 QVariant var;
2564 var.d = QVariant::Private(type.d_ptr);
2565 customConstruct<UseCopy, NonNull>(iface: type.d_ptr, d: &var.d, copy: data);
2566 return var;
2567}
2568
2569#if QT_DEPRECATED_SINCE(6, 0)
2570QT_WARNING_PUSH
2571QT_WARNING_DISABLE_DEPRECATED
2572
2573QDebug operator<<(QDebug dbg, const QVariant::Type p)
2574{
2575 QDebugStateSaver saver(dbg);
2576 dbg.nospace() << "QVariant::"
2577 << (int(p) != int(QMetaType::UnknownType)
2578 ? QMetaType(p).name()
2579 : "Invalid");
2580 return dbg;
2581}
2582
2583QT_WARNING_POP
2584#endif
2585
2586#endif
2587
2588/*! \fn template<typename T> void QVariant::setValue(T &&value)
2589
2590 Stores a copy of \a value. If \c{T} is a type that QVariant
2591 doesn't support, QMetaType is used to store the value. A compile
2592 error will occur if QMetaType doesn't handle the type.
2593
2594 Example:
2595
2596 \snippet code/src_corelib_kernel_qvariant.cpp 4
2597
2598 \sa value(), fromValue(), canConvert()
2599 */
2600
2601/*! \fn template<typename T> void QVariant::setValue(const QVariant &value)
2602
2603 Copies \a value over this QVariant. It is equivalent to simply
2604 assigning \a value to this QVariant.
2605*/
2606
2607/*! \fn template<typename T> void QVariant::setValue(QVariant &&value)
2608
2609 Moves \a value over this QVariant. It is equivalent to simply
2610 move assigning \a value to this QVariant.
2611*/
2612
2613/*! \fn template<typename T> T QVariant::value() const
2614
2615 Returns the stored value converted to the template type \c{T}.
2616 Call canConvert() to find out whether a type can be converted.
2617 If the value cannot be converted, a \l{default-constructed value}
2618 will be returned.
2619
2620 If the type \c{T} is supported by QVariant, this function behaves
2621 exactly as toString(), toInt() etc.
2622
2623 Example:
2624
2625 \snippet code/src_corelib_kernel_qvariant.cpp 5
2626
2627 If the QVariant contains a pointer to a type derived from QObject then
2628 \c{T} may be any QObject type. If the pointer stored in the QVariant can be
2629 qobject_cast to T, then that result is returned. Otherwise \nullptr is
2630 returned. Note that this only works for QObject subclasses which use
2631 the Q_OBJECT macro.
2632
2633 If the QVariant contains a sequential container and \c{T} is QVariantList, the
2634 elements of the container will be converted into \l {QVariant}s and returned as a QVariantList.
2635
2636 \snippet code/src_corelib_kernel_qvariant.cpp 9
2637
2638 \sa setValue(), fromValue(), canConvert(), Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE()
2639*/
2640
2641/*! \fn template<typename T> T QVariant::view()
2642
2643 Returns a mutable view of template type \c{T} on the stored value.
2644 Call canView() to find out whether such a view is supported.
2645 If no such view can be created, returns the stored value converted to the
2646 template type \c{T}. Call canConvert() to find out whether a type can be
2647 converted. If the value can neither be viewed nor converted, a
2648 \l{default-constructed value} will be returned.
2649
2650 \sa canView(), Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE()
2651*/
2652
2653/*! \fn bool QVariant::canConvert() const
2654
2655 Returns \c true if the variant can be converted to the template type \c{T},
2656 otherwise false.
2657
2658 Example:
2659
2660 \snippet code/src_corelib_kernel_qvariant.cpp 6
2661
2662 A QVariant containing a pointer to a type derived from QObject will also return true for this
2663 function if a qobject_cast to the template type \c{T} would succeed. Note that this only works
2664 for QObject subclasses which use the Q_OBJECT macro.
2665
2666 \sa convert()
2667*/
2668
2669/*! \fn bool QVariant::canView() const
2670
2671 Returns \c true if a mutable view of the template type \c{T} can be created on this variant,
2672 otherwise \c false.
2673
2674 \sa value()
2675*/
2676
2677/*! \fn template<typename T> static QVariant QVariant::fromValue(const T &value)
2678
2679 Returns a QVariant containing a copy of \a value. Behaves
2680 exactly like setValue() otherwise.
2681
2682 Example:
2683
2684 \snippet code/src_corelib_kernel_qvariant.cpp 7
2685
2686 \sa setValue(), value()
2687*/
2688
2689/*! \fn template<typename T> static QVariant QVariant::fromValue(T &&value)
2690
2691 \since 6.6
2692 \overload
2693*/
2694
2695/*! \fn template<typename... Types> QVariant QVariant::fromStdVariant(const std::variant<Types...> &value)
2696 \since 5.11
2697
2698 Returns a QVariant with the type and value of the active variant of \a value. If
2699 the active type is std::monostate a default QVariant is returned.
2700
2701 \note With this method you do not need to register the variant as a Qt metatype,
2702 since the std::variant is resolved before being stored. The component types
2703 should be registered however.
2704
2705 \sa fromValue()
2706*/
2707
2708/*!
2709 \fn template<typename... Types> QVariant QVariant::fromStdVariant(std::variant<Types...> &&value)
2710 \since 6.6
2711 \overload
2712*/
2713
2714/*!
2715 \fn template<typename T> T qvariant_cast(const QVariant &value)
2716 \relates QVariant
2717
2718 Returns the given \a value converted to the template type \c{T}.
2719
2720 This function is equivalent to QVariant::value().
2721
2722 \sa QVariant::value()
2723*/
2724
2725/*! \fn template<typename T> T qVariantValue(const QVariant &value)
2726 \relates QVariant
2727 \deprecated
2728
2729 Returns the given \a value converted to the template type \c{T}.
2730
2731 This function is equivalent to
2732 \l{QVariant::value()}{QVariant::value}<T>(\a value).
2733
2734 \note This function was provided as a workaround for MSVC 6
2735 which did not support member template functions. It is advised
2736 to use the other form in new code.
2737
2738 \sa QVariant::value(), qvariant_cast()
2739*/
2740
2741/*! \fn bool qVariantCanConvert(const QVariant &value)
2742 \relates QVariant
2743 \deprecated
2744
2745 Returns \c true if the given \a value can be converted to the
2746 template type specified; otherwise returns \c false.
2747
2748 This function is equivalent to QVariant::canConvert(\a value).
2749
2750 \note This function was provided as a workaround for MSVC 6
2751 which did not support member template functions. It is advised
2752 to use the other form in new code.
2753
2754 \sa QVariant::canConvert()
2755*/
2756
2757/*!
2758 \typedef QVariantList
2759 \relates QVariant
2760
2761 Synonym for QList<QVariant>.
2762*/
2763
2764/*!
2765 \typedef QVariantMap
2766 \relates QVariant
2767
2768 Synonym for QMap<QString, QVariant>.
2769*/
2770
2771/*!
2772 \typedef QVariantHash
2773 \relates QVariant
2774 \since 4.5
2775
2776 Synonym for QHash<QString, QVariant>.
2777*/
2778
2779/*!
2780 \typedef QVariant::DataPtr
2781 \internal
2782*/
2783/*! \typedef QVariant::f_construct
2784 \internal
2785*/
2786
2787/*! \typedef QVariant::f_clear
2788 \internal
2789*/
2790
2791/*! \typedef QVariant::f_null
2792 \internal
2793*/
2794
2795/*! \typedef QVariant::f_load
2796 \internal
2797*/
2798
2799/*! \typedef QVariant::f_save
2800 \internal
2801*/
2802
2803/*! \typedef QVariant::f_compare
2804 \internal
2805*/
2806
2807/*! \typedef QVariant::f_convert
2808 \internal
2809*/
2810
2811/*! \typedef QVariant::f_canConvert
2812 \internal
2813*/
2814
2815/*! \typedef QVariant::f_debugStream
2816 \internal
2817*/
2818
2819/*!
2820 \fn DataPtr &QVariant::data_ptr()
2821 \internal
2822*/
2823
2824/*!
2825 \fn const DataPtr &QVariant::data_ptr() const
2826 \internal
2827*/
2828
2829/*!
2830 \internal
2831 */
2832const void *QtPrivate::QVariantTypeCoercer::convert(const QVariant &value, const QMetaType &type)
2833{
2834 if (type == QMetaType::fromType<QVariant>())
2835 return &value;
2836
2837 if (type == value.metaType())
2838 return value.constData();
2839
2840 if (value.canConvert(targetType: type)) {
2841 converted = value;
2842 if (converted.convert(targetType: type))
2843 return converted.constData();
2844 }
2845
2846 return nullptr;
2847}
2848
2849/*!
2850 \internal
2851 */
2852const void *QtPrivate::QVariantTypeCoercer::coerce(const QVariant &value, const QMetaType &type)
2853{
2854 if (const void *result = convert(value, type))
2855 return result;
2856
2857 converted = QVariant(type);
2858 return converted.constData();
2859}
2860
2861/*!
2862 \class QVariantRef
2863 \since 6.0
2864 \inmodule QtCore
2865 \brief The QVariantRef acts as a non-const reference to a QVariant.
2866
2867 As the generic iterators don't actually instantiate a QVariant on each
2868 step, they cannot return a reference to one from operator*(). QVariantRef
2869 provides the same functionality as an actual reference to a QVariant would,
2870 but is backed by a pointer given as template parameter. The template is
2871 implemented for pointers of type QSequentialIterator and
2872 QAssociativeIterator.
2873*/
2874
2875/*!
2876 \fn template<typename Pointer> QVariantRef<Pointer>::QVariantRef(const Pointer *pointer)
2877
2878 Creates a QVariantRef from an \a pointer.
2879 */
2880
2881/*!
2882 \fn template<typename Pointer> QVariantRef<Pointer> &QVariantRef<Pointer>::operator=(const QVariant &value)
2883
2884 Assigns a new \a value to the value pointed to by the pointer this
2885 QVariantRef refers to.
2886 */
2887
2888/*!
2889 \fn template<typename Pointer> QVariantRef<Pointer> &QVariantRef<Pointer>::operator=(const QVariantRef &value)
2890
2891 Assigns a new \a value to the value pointed to by the pointer this
2892 QVariantRef refers to.
2893 */
2894
2895/*!
2896 \fn template<typename Pointer> QVariantRef<Pointer> &QVariantRef<Pointer>::operator=(QVariantRef &&value)
2897
2898 Assigns a new \a value to the value pointed to by the pointer this
2899 QVariantRef refers to.
2900*/
2901
2902/*!
2903 \fn template<typename Pointer> QVariantRef<Pointer>::operator QVariant() const
2904
2905 Resolves the QVariantRef to an actual QVariant.
2906*/
2907
2908/*!
2909 \fn template<typename Pointer> void swap(QVariantRef<Pointer> a, QVariantRef<Pointer> b)
2910
2911 Swaps the values pointed to by the pointers the QVariantRefs
2912 \a a and \a b refer to.
2913*/
2914
2915/*!
2916 \class QVariantConstPointer
2917 \since 6.0
2918 \inmodule QtCore
2919 \brief Emulated const pointer to QVariant based on a pointer.
2920
2921 QVariantConstPointer wraps a QVariant and returns it from its operator*().
2922 This makes it suitable as replacement for an actual const pointer. We cannot
2923 return an actual const pointer from generic iterators as the iterators don't
2924 hold an actual QVariant.
2925*/
2926
2927/*!
2928 Constructs a QVariantConstPointer from a \a variant.
2929 */
2930QVariantConstPointer::QVariantConstPointer(QVariant variant)
2931 : m_variant(std::move(variant))
2932{
2933}
2934
2935/*!
2936 Dereferences the QVariantConstPointer to retrieve its internal QVariant.
2937 */
2938QVariant QVariantConstPointer::operator*() const
2939{
2940 return m_variant;
2941}
2942
2943/*!
2944 Returns a const pointer to the QVariant, conforming to the
2945 conventions for operator->().
2946 */
2947const QVariant *QVariantConstPointer::operator->() const
2948{
2949 return &m_variant;
2950}
2951
2952/*!
2953 \class QVariantPointer
2954 \since 6.0
2955 \inmodule QtCore
2956 \brief QVariantPointer is a template class that emulates a pointer to QVariant based on a pointer.
2957
2958 QVariantConstPointer wraps a pointer and returns QVariantRef to it from its
2959 operator*(). This makes it suitable as replacement for an actual pointer. We
2960 cannot return an actual pointer from generic iterators as the iterators don't
2961 hold an actual QVariant.
2962*/
2963
2964/*!
2965 \fn template<typename Pointer> QVariantPointer<Pointer>::QVariantPointer(const Pointer *pointer)
2966
2967 Constructs a QVariantPointer from the given \a pointer.
2968 */
2969
2970/*!
2971 \fn template<typename Pointer> QVariantRef<Pointer> QVariantPointer<Pointer>::operator*() const
2972
2973 Dereferences the QVariantPointer to a QVariantRef.
2974 */
2975
2976/*!
2977 \fn template<typename Pointer> Pointer QVariantPointer<Pointer>::operator->() const
2978
2979 Dereferences and returns the pointer. The pointer is expected to also
2980 implement operator->().
2981 */
2982
2983QT_END_NAMESPACE
2984

source code of qtbase/src/corelib/kernel/qvariant.cpp