summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qvariant.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qvariant.cpp')
-rw-r--r--src/corelib/kernel/qvariant.cpp1186
1 files changed, 654 insertions, 532 deletions
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index c16e669c2c..92a44c462b 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -1,50 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qvariant.h"
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2021 Intel Corporation.
+// Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qvariant_p.h"
#include "qbitarray.h"
#include "qbytearray.h"
#include "qdatastream.h"
#include "qdebug.h"
#include "qmap.h"
+#include "qhash.h"
#include "qdatetime.h"
#if QT_CONFIG(easingcurve)
#include "qeasingcurve.h"
@@ -71,7 +36,6 @@
#include "qjsondocument.h"
#include "qbytearraylist.h"
#endif
-#include "private/qvariant_p.h"
#include "private/qlocale_p.h"
#include "qmetatype_p.h"
#include <qmetaobject.h>
@@ -83,32 +47,43 @@
#include "qline.h"
#endif
+#include <memory>
+
#include <cmath>
#include <float.h>
#include <cstring>
QT_BEGIN_NAMESPACE
-namespace { // annonymous used to hide QVariant handlers
+using namespace Qt::StringLiterals;
+
+namespace { // anonymous used to hide QVariant handlers
+
+static qlonglong qMetaTypeNumberBySize(const QVariant::Private *d)
+{
+ switch (d->typeInterface()->size) {
+ case 1:
+ return d->get<signed char>();
+ case 2:
+ return d->get<short>();
+ case 4:
+ return d->get<int>();
+ case 8:
+ return d->get<qlonglong>();
+ }
+ Q_UNREACHABLE_RETURN(0);
+}
-/*!
- \internal
- */
static qlonglong qMetaTypeNumber(const QVariant::Private *d)
{
- switch (d->typeId()) {
+ switch (d->typeInterface()->typeId) {
case QMetaType::Int:
- return d->get<int>();
case QMetaType::LongLong:
- return d->get<qlonglong>();
case QMetaType::Char:
- return qlonglong(d->get<char>());
case QMetaType::SChar:
- return qlonglong(d->get<signed char>());
case QMetaType::Short:
- return qlonglong(d->get<short>());
case QMetaType::Long:
- return qlonglong(d->get<long>());
+ return qMetaTypeNumberBySize(d);
case QMetaType::Float:
return qRound64(d->get<float>());
case QMetaType::Double:
@@ -120,54 +95,46 @@ static qlonglong qMetaTypeNumber(const QVariant::Private *d)
return d->get<QCborValue>().toInteger();
#endif
}
- Q_ASSERT(false);
- return 0;
+ Q_UNREACHABLE_RETURN(0);
}
static qulonglong qMetaTypeUNumber(const QVariant::Private *d)
{
- switch (d->typeId()) {
- case QMetaType::UInt:
- return d->get<unsigned int>();
- case QMetaType::ULongLong:
- return d->get<qulonglong>();
- case QMetaType::UChar:
+ switch (d->typeInterface()->size) {
+ case 1:
return d->get<unsigned char>();
- case QMetaType::UShort:
+ case 2:
return d->get<unsigned short>();
- case QMetaType::ULong:
- return d->get<unsigned long>();
+ case 4:
+ return d->get<unsigned int>();
+ case 8:
+ return d->get<qulonglong>();
}
- Q_ASSERT(false);
- return 0;
+ Q_UNREACHABLE_RETURN(0);
}
-static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok, bool allowStringToBool = false)
+static std::optional<qlonglong> qConvertToNumber(const QVariant::Private *d, bool allowStringToBool = false)
{
- *ok = true;
-
- switch (uint(d->typeId())) {
+ bool ok;
+ switch (d->typeInterface()->typeId) {
case QMetaType::QString: {
const QString &s = d->get<QString>();
- qlonglong l = s.toLongLong(ok);
- if (*ok)
+ if (qlonglong l = s.toLongLong(&ok); ok)
return l;
if (allowStringToBool) {
- if (s == QLatin1String("false") || s == QLatin1String("0")) {
- *ok = true;
+ if (s == "false"_L1 || s == "0"_L1)
return 0;
- }
- if (s == QLatin1String("true") || s == QLatin1String("1")) {
- *ok = true;
+ if (s == "true"_L1 || s == "1"_L1)
return 1;
- }
}
- return 0;
+ return std::nullopt;
}
case QMetaType::QChar:
return d->get<QChar>().unicode();
case QMetaType::QByteArray:
- return d->get<QByteArray>().toLongLong(ok);
+ if (qlonglong l = d->get<QByteArray>().toLongLong(&ok); ok)
+ return l;
+ return std::nullopt;
case QMetaType::Bool:
return qlonglong(d->get<bool>());
#ifndef QT_BOOTSTRAPPED
@@ -192,47 +159,42 @@ static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok, bool all
case QMetaType::ULongLong:
case QMetaType::UInt:
case QMetaType::UChar:
+ case QMetaType::Char16:
+ case QMetaType::Char32:
case QMetaType::UShort:
case QMetaType::ULong:
-
return qlonglong(qMetaTypeUNumber(d));
}
- QMetaType typeInfo = d->type();
- if (typeInfo.flags() & QMetaType::IsEnumeration
- || d->typeId() == QMetaType::QCborSimpleType) {
- switch (typeInfo.sizeOf()) {
- case 1:
- return d->get<signed char>();
- case 2:
- return d->get<short>();
- case 4:
- return d->get<int>();
- case 8:
- return d->get<qlonglong>();
- }
- }
+ if (d->typeInterface()->flags & QMetaType::IsEnumeration
+ || d->typeInterface()->typeId == QMetaType::QCborSimpleType)
+ return qMetaTypeNumberBySize(d);
- *ok = false;
- return Q_INT64_C(0);
+ return std::nullopt;
}
-static qreal qConvertToRealNumber(const QVariant::Private *d, bool *ok)
+static std::optional<double> qConvertToRealNumber(const QVariant::Private *d)
{
- *ok = true;
- switch (uint(d->typeId())) {
+ bool ok;
+ switch (d->typeInterface()->typeId) {
case QMetaType::QString:
- return d->get<QString>().toDouble(ok);
+ if (double r = d->get<QString>().toDouble(&ok); ok)
+ return r;
+ return std::nullopt;
case QMetaType::Double:
- return qreal(d->get<double>());
+ return d->get<double>();
case QMetaType::Float:
- return qreal(d->get<float>());
+ return double(d->get<float>());
+ case QMetaType::Float16:
+ return double(d->get<qfloat16>());
case QMetaType::ULongLong:
case QMetaType::UInt:
case QMetaType::UChar:
+ case QMetaType::Char16:
+ case QMetaType::Char32:
case QMetaType::UShort:
case QMetaType::ULong:
- return qreal(qMetaTypeUNumber(d));
+ return double(qMetaTypeUNumber(d));
#ifndef QT_BOOTSTRAPPED
case QMetaType::QCborValue:
return d->get<QCborValue>().toDouble();
@@ -241,58 +203,118 @@ static qreal qConvertToRealNumber(const QVariant::Private *d, bool *ok)
#endif
default:
// includes enum conversion as well as invalid types
- return qreal(qConvertToNumber(d, ok));
+ if (std::optional<qlonglong> l = qConvertToNumber(d))
+ return double(*l);
+ return std::nullopt;
}
}
-// the type of d has already been set, but other field are not set
-static void customConstruct(QVariant::Private *d, const void *copy)
+static bool isValidMetaTypeForVariant(const QtPrivate::QMetaTypeInterface *iface, const void *copy)
{
- QtPrivate::QMetaTypeInterface *iface = d->typeInterface();
- if (!(iface && iface->size)) {
- *d = QVariant::Private();
- return;
+ using namespace QtMetaTypePrivate;
+ if (!iface || iface->size == 0)
+ return false;
+
+ Q_ASSERT(!isInterfaceFor<void>(iface)); // only void should have size 0
+ if (!isCopyConstructible(iface) || !isDestructible(iface)) {
+ // all meta types must be copyable (because QVariant is) and
+ // destructible (because QVariant owns it)
+ qWarning("QVariant: Provided metatype for '%s' does not support destruction and "
+ "copy construction", iface->name);
+ return false;
}
+ if (!copy && !isDefaultConstructible(iface)) {
+ // non-default-constructible types are acceptable, but not if you're
+ // asking us to construct from nothing
+ qWarning("QVariant: Cannot create type '%s' without a default constructor", iface->name);
+ return false;
+ }
+
+ return true;
+}
+
+enum CustomConstructMoveOptions {
+ UseCopy, // custom construct uses the copy ctor unconditionally
+ // future option: TryMove: uses move ctor if available, else copy ctor
+ ForceMove, // custom construct use the move ctor (which must exist)
+};
+
+enum CustomConstructNullabilityOption {
+ MaybeNull, // copy might be null, might be non-null
+ NonNull, // copy is guarantueed to be non-null
+ // future option: AlwaysNull?
+};
+
+// the type of d has already been set, but other field are not set
+template <CustomConstructMoveOptions moveOption = UseCopy, CustomConstructNullabilityOption nullability = MaybeNull>
+static void customConstruct(const QtPrivate::QMetaTypeInterface *iface, QVariant::Private *d,
+ std::conditional_t<moveOption == ForceMove, void *, const void *> copy)
+{
+ using namespace QtMetaTypePrivate;
+ Q_ASSERT(iface);
+ Q_ASSERT(iface->size);
+ Q_ASSERT(!isInterfaceFor<void>(iface));
+ Q_ASSERT(isCopyConstructible(iface));
+ Q_ASSERT(isDestructible(iface));
+ Q_ASSERT(copy || isDefaultConstructible(iface));
+ if constexpr (moveOption == ForceMove)
+ Q_ASSERT(isMoveConstructible(iface));
+ if constexpr (nullability == NonNull)
+ Q_ASSERT(copy != nullptr);
+
+ // need to check for nullptr_t here, as this can get called by fromValue(nullptr). fromValue() uses
+ // std::addressof(value) which in this case returns the address of the nullptr object.
+ // ### Qt 7: remove nullptr_t special casing
+ d->is_null = !copy QT6_ONLY(|| isInterfaceFor<std::nullptr_t>(iface));
if (QVariant::Private::canUseInternalSpace(iface)) {
- // QVariant requires type to be copy and default constructible
- Q_ASSERT(iface->copyCtr);
- Q_ASSERT(iface->defaultCtr);
- if (copy)
- iface->copyCtr(iface, &d->data, copy);
- else
- iface->defaultCtr(iface, &d->data);
d->is_shared = false;
- } else {
- d->data.shared = QVariant::PrivateShared::create(iface);
- if (copy)
- iface->copyCtr(iface, d->data.shared->data(), copy);
+ if (!copy && !iface->defaultCtr)
+ return; // trivial default constructor and it's OK to build in 0-filled storage, which we've already done
+ if constexpr (moveOption == ForceMove && nullability == NonNull)
+ moveConstruct(iface, d->data.data, copy);
else
- iface->defaultCtr(iface, d->data.shared->data());
+ construct(iface, d->data.data, copy);
+ } else {
+ d->data.shared = customConstructShared(iface->size, iface->alignment, [=](void *where) {
+ if constexpr (moveOption == ForceMove && nullability == NonNull)
+ moveConstruct(iface, where, copy);
+ else
+ construct(iface, where, copy);
+ });
d->is_shared = true;
}
- // need to check for nullptr_t here, as this can get called by fromValue(nullptr). fromValue() uses
- // std::addressof(value) which in this case returns the address of the nullptr object.
- d->is_null = !copy || QMetaType(iface) == QMetaType::fromType<std::nullptr_t>();
}
static void customClear(QVariant::Private *d)
{
- auto iface = reinterpret_cast<QtPrivate::QMetaTypeInterface *>(d->packedType << 2);
+ const QtPrivate::QMetaTypeInterface *iface = d->typeInterface();
if (!iface)
return;
if (!d->is_shared) {
- if (iface->dtor)
- iface->dtor(iface, &d->data);
+ QtMetaTypePrivate::destruct(iface, d->data.data);
} else {
- if (iface->dtor)
- iface->dtor(iface, d->data.shared->data());
+ QtMetaTypePrivate::destruct(iface, d->data.shared->data());
QVariant::PrivateShared::free(d->data.shared);
}
}
+static QVariant::Private clonePrivate(const QVariant::Private &other)
+{
+ QVariant::Private d = other;
+ if (d.is_shared) {
+ d.data.shared->ref.ref();
+ } else if (const QtPrivate::QMetaTypeInterface *iface = d.typeInterface()) {
+ Q_ASSERT(d.canUseInternalSpace(iface));
+
+ // if not trivially copyable, ask to copy
+ if (iface->copyCtr)
+ QtMetaTypePrivate::copyConstruct(iface, d.data.data, other.data.data);
+ }
+ return d;
+}
-} // annonymous used to hide QVariant handlers
+} // anonymous used to hide QVariant handlers
/*!
\class QVariant
@@ -302,6 +324,7 @@ static void customClear(QVariant::Private *d)
\ingroup objectmodel
\ingroup shared
+ \compares equality
Because C++ forbids unions from including types that have
non-default constructors or destructors, most interesting Qt
@@ -378,7 +401,7 @@ static void customClear(QVariant::Private *d)
*/
/*!
- \deprecated Use QMetaType::Type instead.
+ \deprecated Use \l QMetaType::Type instead.
\enum QVariant::Type
This enum type defines the types of variable that a QVariant can
@@ -399,7 +422,7 @@ static void customClear(QVariant::Private *d)
\value EasingCurve a QEasingCurve
\value Uuid a QUuid
\value ModelIndex a QModelIndex
- \value PersistentModelIndex a QPersistentModelIndex (since 5.5)
+ \value [since 5.5] PersistentModelIndex a QPersistentModelIndex
\value Font a QFont
\value Hash a QVariantHash
\value Icon a QIcon
@@ -494,24 +517,18 @@ void QVariant::create(int type, const void *copy)
*/
void QVariant::create(QMetaType type, const void *copy)
{
- d = Private(type);
- customConstruct(&d, copy);
+ *this = QVariant::fromMetaType(type, copy);
}
/*!
\fn QVariant::~QVariant()
Destroys the QVariant and the contained object.
-
- Note that subclasses that reimplement clear() should reimplement
- the destructor to call clear(). This destructor calls clear(), but
- because it is the destructor, QVariant::clear() is called rather
- than a subclass's clear().
*/
QVariant::~QVariant()
{
- if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared))
+ if (!d.is_shared || !d.data.shared->ref.deref())
customClear(&d);
}
@@ -523,32 +540,121 @@ QVariant::~QVariant()
*/
QVariant::QVariant(const QVariant &p)
- : d(p.d)
+ : d(clonePrivate(p.d))
{
- if (d.is_shared) {
- d.data.shared->ref.ref();
- return;
+}
+
+/*!
+ \fn template <typename T, typename... Args, QVariant::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)
+
+ \since 6.6
+ Constructs a new variant containing a value of type \c T. The contained
+ value is is initialized with the arguments
+ \c{std::forward<Args>(args)...}.
+
+ This overload only participates in overload resolution if \c T can be
+ constructed from \a args.
+
+ This constructor is provided for STL/std::any compatibility.
+
+ \overload
+ */
+
+/*!
+
+ \fn template <typename T, typename U, typename... Args, QVariant::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)
+
+ \since 6.6
+ \overload
+ This overload exists to support types with constructors taking an
+ \c initializer_list. It behaves otherwise equivalent to the
+ non-initializer list \c{in_place_type_t} overload.
+*/
+
+
+/*!
+ \fn template <typename T, typename... Args, QVariant::if_constructible<T, Args...> = true> QVariant::emplace(Args&&... args)
+
+ \since 6.6
+ Replaces the object currently held in \c{*this} with an object of
+ type \c{T}, constructed from \a{args}\c{...}. If \c{*this} was non-null,
+ the previously held object is destroyed first.
+ If possible, this method will reuse memory allocated by the QVariant.
+ Returns a reference to the newly-created object.
+ */
+
+/*!
+ \fn template <typename T, typename U, typename... Args, QVariant::if_constructible<T, std::initializer_list<U> &, Args...> = true> QVariant::emplace(std::initializer_list<U> list, Args&&... args)
+
+ \since 6.6
+ \overload
+ This overload exists to support types with constructors taking an
+ \c initializer_list. It behaves otherwise equivalent to the
+ non-initializer list overload.
+*/
+
+QVariant::QVariant(std::in_place_t, QMetaType type) : d(type.iface())
+{
+ // we query the metatype instead of detecting it at compile time
+ // so that we can change relocatability of internal types
+ if (!Private::canUseInternalSpace(type.iface())) {
+ d.data.shared = PrivateShared::create(type.sizeOf(), type.alignOf());
+ d.is_shared = true;
}
- QtPrivate::QMetaTypeInterface *iface = d.typeInterface();
- auto other = p.constData();
- if (iface) {
- if (other)
- iface->copyCtr(iface, &d, other);
- else
- iface->defaultCtr(iface, &d);
+}
+
+/*!
+ \internal
+ Returns a pointer to data suitable for placement new
+ of an object of type \a type
+ Changes the variant's metatype to \a type
+ */
+void *QVariant::prepareForEmplace(QMetaType type)
+{
+ /* There are two cases where we can reuse the existing storage
+ (1) The new type fits in QVariant's SBO storage
+ (2) We are using the externally allocated storage, the variant is
+ detached, and the new type fits into the existing storage.
+ In all other cases (3), we cannot reuse the storage.
+ */
+ auto typeFits = [&] {
+ auto newIface = type.iface();
+ auto oldIface = d.typeInterface();
+ auto newSize = PrivateShared::computeAllocationSize(newIface->size, newIface->alignment);
+ auto oldSize = PrivateShared::computeAllocationSize(oldIface->size, oldIface->alignment);
+ return newSize <= oldSize;
+ };
+ if (Private::canUseInternalSpace(type.iface())) { // (1)
+ clear();
+ d.packedType = quintptr(type.iface()) >> 2;
+ return d.data.data;
+ } else if (d.is_shared && isDetached() && typeFits()) { // (2)
+ QtMetaTypePrivate::destruct(d.typeInterface(), d.data.shared->data());
+ // compare QVariant::PrivateShared::create
+ const auto ps = d.data.shared;
+ const auto align = type.alignOf();
+ ps->offset = PrivateShared::computeOffset(ps, align);
+ d.packedType = quintptr(type.iface()) >> 2;
+ return ps->data();
}
+ // (3)
+ QVariant newVariant(std::in_place, type);
+ swap(newVariant);
+ // const cast is safe, we're in a non-const method
+ return const_cast<void *>(d.storage());
}
/*!
- \fn QVariant::QVariant(const QString &val)
+ \fn QVariant::QVariant(const QString &val) noexcept
Constructs a new variant with a string value, \a val.
*/
/*!
- \fn QVariant::QVariant(QLatin1String val)
+ \fn QVariant::QVariant(QLatin1StringView val)
- Constructs a new variant with a string value, \a val.
+ Constructs a new variant with a QString value from the Latin-1
+ string viewed by \a val.
*/
/*!
@@ -567,37 +673,37 @@ QVariant::QVariant(const QVariant &p)
*/
/*!
- \fn QVariant::QVariant(const QStringList &val)
+ \fn QVariant::QVariant(const QStringList &val) noexcept
Constructs a new variant with a string list value, \a val.
*/
/*!
- \fn QVariant::QVariant(const QMap<QString, QVariant> &val)
+ \fn QVariant::QVariant(const QMap<QString, QVariant> &val) noexcept
Constructs a new variant with a map of \l {QVariant}s, \a val.
*/
/*!
- \fn QVariant::QVariant(const QHash<QString, QVariant> &val)
+ \fn QVariant::QVariant(const QHash<QString, QVariant> &val) noexcept
Constructs a new variant with a hash of \l {QVariant}s, \a val.
*/
/*!
- \fn QVariant::QVariant(QDate val)
+ \fn QVariant::QVariant(QDate val) noexcept
Constructs a new variant with a date value, \a val.
*/
/*!
- \fn QVariant::QVariant(QTime val)
+ \fn QVariant::QVariant(QTime val) noexcept
Constructs a new variant with a time value, \a val.
*/
/*!
- \fn QVariant::QVariant(const QDateTime &val)
+ \fn QVariant::QVariant(const QDateTime &val) noexcept
Constructs a new variant with a date/time value, \a val.
*/
@@ -611,14 +717,14 @@ QVariant::QVariant(const QVariant &p)
/*!
\since 5.0
- \fn QVariant::QVariant(const QUuid &val)
+ \fn QVariant::QVariant(QUuid val) noexcept
Constructs a new variant with an uuid value, \a val.
*/
/*!
\since 5.0
- \fn QVariant::QVariant(const QModelIndex &val)
+ \fn QVariant::QVariant(const QModelIndex &val) noexcept
Constructs a new variant with a QModelIndex value, \a val.
*/
@@ -659,135 +765,135 @@ QVariant::QVariant(const QVariant &p)
*/
/*!
- \fn QVariant::QVariant(const QByteArray &val)
+ \fn QVariant::QVariant(const QByteArray &val) noexcept
Constructs a new variant with a bytearray value, \a val.
*/
/*!
- \fn QVariant::QVariant(const QBitArray &val)
+ \fn QVariant::QVariant(const QBitArray &val) noexcept
Constructs a new variant with a bitarray value, \a val.
*/
/*!
- \fn QVariant::QVariant(const QPoint &val)
+ \fn QVariant::QVariant(QPoint val) noexcept
Constructs a new variant with a point value of \a val.
*/
/*!
- \fn QVariant::QVariant(const QPointF &val)
+ \fn QVariant::QVariant(QPointF val) noexcept
Constructs a new variant with a point value of \a val.
*/
/*!
- \fn QVariant::QVariant(const QRectF &val)
+ \fn QVariant::QVariant(QRectF val)
Constructs a new variant with a rect value of \a val.
*/
/*!
- \fn QVariant::QVariant(const QLineF &val)
+ \fn QVariant::QVariant(QLineF val) noexcept
Constructs a new variant with a line value of \a val.
*/
/*!
- \fn QVariant::QVariant(const QLine &val)
+ \fn QVariant::QVariant(QLine val) noexcept
Constructs a new variant with a line value of \a val.
*/
/*!
- \fn QVariant::QVariant(const QRect &val)
+ \fn QVariant::QVariant(QRect val) noexcept
Constructs a new variant with a rect value of \a val.
*/
/*!
- \fn QVariant::QVariant(const QSize &val)
+ \fn QVariant::QVariant(QSize val) noexcept
Constructs a new variant with a size value of \a val.
*/
/*!
- \fn QVariant::QVariant(const QSizeF &val)
+ \fn QVariant::QVariant(QSizeF val) noexcept
Constructs a new variant with a size value of \a val.
*/
/*!
- \fn QVariant::QVariant(const QUrl &val)
+ \fn QVariant::QVariant(const QUrl &val) noexcept
Constructs a new variant with a url value of \a val.
*/
/*!
- \fn QVariant::QVariant(int val)
+ \fn QVariant::QVariant(int val) noexcept
Constructs a new variant with an integer value, \a val.
*/
/*!
- \fn QVariant::QVariant(uint val)
+ \fn QVariant::QVariant(uint val) noexcept
Constructs a new variant with an unsigned integer value, \a val.
*/
/*!
- \fn QVariant::QVariant(qlonglong val)
+ \fn QVariant::QVariant(qlonglong val) noexcept
Constructs a new variant with a long long integer value, \a val.
*/
/*!
- \fn QVariant::QVariant(qulonglong val)
+ \fn QVariant::QVariant(qulonglong val) noexcept
Constructs a new variant with an unsigned long long integer value, \a val.
*/
/*!
- \fn QVariant::QVariant(bool val)
+ \fn QVariant::QVariant(bool val) noexcept
Constructs a new variant with a boolean value, \a val.
*/
/*!
- \fn QVariant::QVariant(double val)
+ \fn QVariant::QVariant(double val) noexcept
Constructs a new variant with a floating point value, \a val.
*/
/*!
- \fn QVariant::QVariant(float val)
+ \fn QVariant::QVariant(float val) noexcept
Constructs a new variant with a floating point value, \a val.
\since 4.6
*/
/*!
- \fn QVariant::QVariant(const QList<QVariant> &val)
+ \fn QVariant::QVariant(const QList<QVariant> &val) noexcept
Constructs a new variant with a list value, \a val.
*/
/*!
- \fn QVariant::QVariant(QChar c)
+ \fn QVariant::QVariant(QChar c) noexcept
Constructs a new variant with a char value, \a c.
*/
/*!
- \fn QVariant::QVariant(const QLocale &l)
+ \fn QVariant::QVariant(const QLocale &l) noexcept
Constructs a new variant with a locale value, \a l.
*/
/*!
- \fn QVariant::QVariant(const QRegularExpression &re)
+ \fn QVariant::QVariant(const QRegularExpression &re) noexcept
\since 5.0
@@ -795,7 +901,7 @@ QVariant::QVariant(const QVariant &p)
*/
/*! \fn QVariant::QVariant(Type type)
- \deprecated
+ \deprecated [6.0] Use the constructor taking a QMetaType instead.
Constructs an uninitialized variant of type \a type. This will create a
variant in a special null state that if accessed will return a default
@@ -805,153 +911,100 @@ QVariant::QVariant(const QVariant &p)
*/
/*!
- Constructs variant of type \a type, and initializes with
- \a copy if \a copy is not \nullptr.
+ Constructs a variant of type \a type, and initializes it with
+ a copy of \c{*copy} if \a copy is not \nullptr (in which case, \a copy
+ must point to an object of type \a type).
- Note that you have to pass the address of the variable you want stored.
+ Note that you have to pass the address of the object you want stored.
Usually, you never have to use this constructor, use QVariant::fromValue()
instead to construct variants from the pointer types represented by
\c QMetaType::VoidStar, and \c QMetaType::QObjectStar.
- \sa QVariant::fromValue(), QMetaType::Type
+ If \a type does not support copy construction and \a copy is not \nullptr,
+ the variant will be invalid. Similarly, if \a copy is \nullptr and
+ \a type does not support default construction, the variant will be
+ invalid.
+
+ \sa QVariant::fromMetaType, QVariant::fromValue(), QMetaType::Type
*/
-QVariant::QVariant(QMetaType type, const void *copy) : d(type)
-{
- customConstruct(&d, copy);
-}
-
-QVariant::QVariant(int val)
- : d(QMetaType::fromType<int>())
-{ d.set(val); }
-QVariant::QVariant(uint val)
- : d(QMetaType::fromType<uint>())
-{ d.set(val); }
-QVariant::QVariant(qlonglong val)
- : d(QMetaType::fromType<qlonglong>())
-{ d.set(val); }
-QVariant::QVariant(qulonglong val)
- : d(QMetaType::fromType<qulonglong>())
-{ d.set(val); }
-QVariant::QVariant(bool val)
- : d(QMetaType::fromType<bool>())
-{ d.set(val); }
-QVariant::QVariant(double val)
- : d(QMetaType::fromType<double>())
-{ d.set(val); }
-QVariant::QVariant(float val)
- : d(QMetaType::fromType<float>())
-{ d.set(val); }
-
-QVariant::QVariant(const QByteArray &val)
- : d(QMetaType::fromType<QByteArray>())
-{ v_construct<QByteArray>(&d, val); }
-QVariant::QVariant(const QBitArray &val)
- : d(QMetaType::fromType<QBitArray>())
-{ v_construct<QBitArray>(&d, val); }
-QVariant::QVariant(const QString &val)
- : d(QMetaType::fromType<QString>())
-{ v_construct<QString>(&d, val); }
-QVariant::QVariant(QChar val)
- : d(QMetaType::fromType<QChar>())
-{ v_construct<QChar>(&d, val); }
-QVariant::QVariant(QLatin1String val)
- : d(QMetaType::fromType<QString>())
-{ v_construct<QString>(&d, val); }
-QVariant::QVariant(const QStringList &val)
- : d(QMetaType::fromType<QStringList>())
-{ v_construct<QStringList>(&d, val); }
-
-QVariant::QVariant(QDate val)
- : d(QMetaType::fromType<QDate>())
-{ v_construct<QDate>(&d, val); }
-QVariant::QVariant(QTime val)
- : d(QMetaType::fromType<QTime>())
-{ v_construct<QTime>(&d, val); }
-QVariant::QVariant(const QDateTime &val)
- : d(QMetaType::fromType<QDateTime>())
-{ v_construct<QDateTime>(&d, val); }
+QVariant::QVariant(QMetaType type, const void *copy)
+ : d()
+{
+ *this = fromMetaType(type, copy);
+}
+
+QVariant::QVariant(int val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(uint val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(qlonglong val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(qulonglong val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(bool val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(double val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(float val) noexcept : d(std::piecewise_construct_t{}, val) {}
+
+QVariant::QVariant(const QByteArray &val) noexcept : d(std::piecewise_construct_t{}, val) {}
+#ifndef QT_BOOTSTRAPPED
+QVariant::QVariant(const QBitArray &val) noexcept : d(std::piecewise_construct_t{}, val) {}
+#endif
+QVariant::QVariant(const QString &val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(QChar val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(const QStringList &val) noexcept : d(std::piecewise_construct_t{}, val) {}
+
+QVariant::QVariant(QDate val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(QTime val) noexcept : d(std::piecewise_construct_t{}, val) {}
+QVariant::QVariant(const QDateTime &val) noexcept : d(std::piecewise_construct_t{}, val) {}
+
+QVariant::QVariant(const QList<QVariant> &list) noexcept : d(std::piecewise_construct_t{}, list) {}
+QVariant::QVariant(const QMap<QString, QVariant> &map) noexcept : d(std::piecewise_construct_t{}, map) {}
+QVariant::QVariant(const QHash<QString, QVariant> &hash) noexcept : d(std::piecewise_construct_t{}, hash) {}
+
+QVariant::QVariant(QLatin1StringView val) : QVariant(QString(val)) {}
+
#if QT_CONFIG(easingcurve)
-QVariant::QVariant(const QEasingCurve &val)
- : d(QMetaType::fromType<QEasingCurve>())
-{ v_construct<QEasingCurve>(&d, val); }
+QVariant::QVariant(const QEasingCurve &val) : d(std::piecewise_construct_t{}, val) {}
#endif
-QVariant::QVariant(const QList<QVariant> &list)
- : d(QMetaType::fromType<QList<QVariant>>())
-{ v_construct<QVariantList>(&d, list); }
-QVariant::QVariant(const QMap<QString, QVariant> &map)
- : d(QMetaType::fromType<QMap<QString, QVariant>>())
-{ v_construct<QVariantMap>(&d, map); }
-QVariant::QVariant(const QHash<QString, QVariant> &hash)
- : d(QMetaType::fromType<QHash<QString, QVariant>>())
-{ v_construct<QVariantHash>(&d, hash); }
#ifndef QT_NO_GEOM_VARIANT
-QVariant::QVariant(const QPoint &pt)
- : d(QMetaType::fromType<QPoint>())
-{ v_construct<QPoint>(&d, pt); }
-QVariant::QVariant(const QPointF &pt)
- : d(QMetaType::fromType<QPointF>())
-{ v_construct<QPointF>(&d, pt); }
-QVariant::QVariant(const QRectF &r)
- : d(QMetaType::fromType<QRectF>())
-{ v_construct<QRectF>(&d, r); }
-QVariant::QVariant(const QLineF &l)
- : d(QMetaType::fromType<QLineF>())
-{ v_construct<QLineF>(&d, l); }
-QVariant::QVariant(const QLine &l)
- : d(QMetaType::fromType<QLine>())
-{ v_construct<QLine>(&d, l); }
-QVariant::QVariant(const QRect &r)
- : d(QMetaType::fromType<QRect>())
-{ v_construct<QRect>(&d, r); }
-QVariant::QVariant(const QSize &s)
- : d(QMetaType::fromType<QSize>())
-{ v_construct<QSize>(&d, s); }
-QVariant::QVariant(const QSizeF &s)
- : d(QMetaType::fromType<QSizeF>())
-{ v_construct<QSizeF>(&d, s); }
+QVariant::QVariant(QPoint pt) noexcept
+ : d(std::piecewise_construct_t{}, pt) {}
+QVariant::QVariant(QPointF pt) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>)
+ : d(std::piecewise_construct_t{}, pt) {}
+QVariant::QVariant(QRect r) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>)
+ : d(std::piecewise_construct_t{}, r) {}
+QVariant::QVariant(QRectF r) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>)
+ : d(std::piecewise_construct_t{}, r) {}
+QVariant::QVariant(QLine l) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>)
+ : d(std::piecewise_construct_t{}, l) {}
+QVariant::QVariant(QLineF l) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>)
+ : d(std::piecewise_construct_t{}, l) {}
+QVariant::QVariant(QSize s) noexcept
+ : d(std::piecewise_construct_t{}, s) {}
+QVariant::QVariant(QSizeF s) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>)
+ : d(std::piecewise_construct_t{}, s) {}
#endif
#ifndef QT_BOOTSTRAPPED
-QVariant::QVariant(const QUrl &u)
- : d(QMetaType::fromType<QUrl>())
-{ v_construct<QUrl>(&d, u); }
+QVariant::QVariant(const QUrl &u) noexcept : d(std::piecewise_construct_t{}, u) {}
#endif
-QVariant::QVariant(const QLocale &l)
- : d(QMetaType::fromType<QLocale>())
-{ v_construct<QLocale>(&d, l); }
+QVariant::QVariant(const QLocale &l) noexcept : d(std::piecewise_construct_t{}, l) {}
#if QT_CONFIG(regularexpression)
-QVariant::QVariant(const QRegularExpression &re)
- : d(QMetaType::fromType<QRegularExpression>())
-{ v_construct<QRegularExpression>(&d, re); }
+QVariant::QVariant(const QRegularExpression &re) noexcept : d(std::piecewise_construct_t{}, re) {}
#endif // QT_CONFIG(regularexpression)
-QVariant::QVariant(const QUuid &uuid)
- : d(QMetaType::fromType<QUuid>())
-{ v_construct<QUuid>(&d, uuid); }
+QVariant::QVariant(QUuid uuid) noexcept(Private::FitsInInternalSize<16>) : d(std::piecewise_construct_t{}, uuid) {}
#ifndef QT_BOOTSTRAPPED
-QVariant::QVariant(const QJsonValue &jsonValue)
- : d(QMetaType::fromType<QJsonValue>())
-{ v_construct<QJsonValue>(&d, jsonValue); }
-QVariant::QVariant(const QJsonObject &jsonObject)
- : d(QMetaType::fromType<QJsonObject>())
-{ v_construct<QJsonObject>(&d, jsonObject); }
-QVariant::QVariant(const QJsonArray &jsonArray)
- : d(QMetaType::fromType<QJsonArray>())
-{ v_construct<QJsonArray>(&d, jsonArray); }
-QVariant::QVariant(const QJsonDocument &jsonDocument)
- : d(QMetaType::fromType<QJsonDocument>())
-{ v_construct<QJsonDocument>(&d, jsonDocument); }
+QVariant::QVariant(const QJsonValue &jsonValue) noexcept(Private::FitsInInternalSize<sizeof(CborValueStandIn)>)
+ : d(std::piecewise_construct_t{}, jsonValue)
+{ static_assert(sizeof(CborValueStandIn) == sizeof(QJsonValue)); }
+QVariant::QVariant(const QJsonObject &jsonObject) noexcept : d(std::piecewise_construct_t{}, jsonObject) {}
+QVariant::QVariant(const QJsonArray &jsonArray) noexcept : d(std::piecewise_construct_t{}, jsonArray) {}
+QVariant::QVariant(const QJsonDocument &jsonDocument) : d(std::piecewise_construct_t{}, jsonDocument) {}
#endif // QT_BOOTSTRAPPED
#if QT_CONFIG(itemmodel)
-QVariant::QVariant(const QModelIndex &modelIndex)
- : d(QMetaType::fromType<QModelIndex>())
-{ v_construct<QModelIndex>(&d, modelIndex); }
-QVariant::QVariant(const QPersistentModelIndex &modelIndex)
- : d(QMetaType::fromType<QPersistentModelIndex>())
-{ v_construct<QPersistentModelIndex>(&d, modelIndex); }
+QVariant::QVariant(const QModelIndex &modelIndex) noexcept(Private::FitsInInternalSize<8 + 2 * sizeof(quintptr)>)
+ : d(std::piecewise_construct_t{}, modelIndex) {}
+QVariant::QVariant(const QPersistentModelIndex &modelIndex) : d(std::piecewise_construct_t{}, modelIndex) {}
#endif
/*! \fn QVariant::Type QVariant::type() const
- \deprecated
+ \deprecated [6.0] Use typeId() or metaType() instead.
Returns the storage type of the value stored in the variant.
Although this function is declared as returning QVariant::Type,
@@ -1014,21 +1067,7 @@ QVariant &QVariant::operator=(const QVariant &variant)
return *this;
clear();
- if (variant.d.is_shared) {
- variant.d.data.shared->ref.ref();
- d = variant.d;
- } else {
- d = variant.d;
- QtPrivate::QMetaTypeInterface *iface = d.typeInterface();
- const void *other = variant.constData();
- if (iface) {
- if (other)
- iface->copyCtr(iface, &d, other);
- else
- iface->defaultCtr(iface, &d);
- }
- }
-
+ d = clonePrivate(variant.d);
return *this;
}
@@ -1051,8 +1090,10 @@ void QVariant::detach()
if (!d.is_shared || d.data.shared->ref.loadRelaxed() == 1)
return;
- Private dd(d.type());
- customConstruct(&dd, constData());
+ Q_ASSERT(isValidMetaTypeForVariant(d.typeInterface(), constData()));
+ Private dd(d.typeInterface());
+ // null variant is never shared; anything else is NonNull
+ customConstruct<UseCopy, NonNull>(d.typeInterface(), &dd, constData());
if (!d.data.shared->ref.deref())
customClear(&d);
d.data.shared = dd.data.shared;
@@ -1081,14 +1122,14 @@ const char *QVariant::typeName() const
*/
void QVariant::clear()
{
- if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared))
+ if (!d.is_shared || !d.data.shared->ref.deref())
customClear(&d);
d = {};
}
/*!
\fn const char *QVariant::typeToName(int typeId)
- \deprecated Use QMetaType instead
+ \deprecated [6.0] Use \c QMetaType(typeId).name() instead.
Converts the int representation of the storage type, \a typeId, to
its string representation.
@@ -1098,7 +1139,7 @@ void QVariant::clear()
/*!
\fn QVariant::Type QVariant::nameToType(const char *name)
- \deprecated Use QMetaType instead
+ \deprecated [6.0] Use \c QMetaType::fromName(name).id() instead
Converts the string representation of the storage type given in \a
name, to its enum representation.
@@ -1243,7 +1284,7 @@ void QVariant::load(QDataStream &s)
void *data = const_cast<void *>(constData());
if (!d.type().load(s, data)) {
s.setStatus(QDataStream::ReadCorruptData);
- qWarning("QVariant::load: unable to load type %d.", d.typeId());
+ qWarning("QVariant::load: unable to load type %d.", d.type().id());
}
}
@@ -1255,7 +1296,7 @@ void QVariant::load(QDataStream &s)
*/
void QVariant::save(QDataStream &s) const
{
- quint32 typeId = d.typeId();
+ quint32 typeId = d.type().id();
bool saveAsUserType = false;
if (typeId >= QMetaType::User) {
typeId = QMetaType::User;
@@ -1314,13 +1355,17 @@ void QVariant::save(QDataStream &s) const
}
}
const char *typeName = nullptr;
- if (saveAsUserType)
- typeName = d.type().name();
+ if (saveAsUserType) {
+ if (s.version() < QDataStream::Qt_6_0)
+ typeName = QtMetaTypePrivate::typedefNameForType(d.type().d_ptr);
+ if (!typeName)
+ typeName = d.type().name();
+ }
s << typeId;
if (s.version() >= QDataStream::Qt_4_2)
s << qint8(d.is_null);
if (typeName)
- s << d.type().name();
+ s << typeName;
if (!isValid()) {
if (s.version() < QDataStream::Qt_5_0)
@@ -1330,16 +1375,28 @@ void QVariant::save(QDataStream &s) const
if (!d.type().save(s, constData())) {
qWarning("QVariant::save: unable to save type '%s' (type id: %d).\n",
- d.type().name(), d.typeId());
+ d.type().name(), d.type().id());
Q_ASSERT_X(false, "QVariant::save", "Invalid type to save");
}
}
/*!
\since 4.4
+ \relates QVariant
Reads a variant \a p from the stream \a s.
+ \note If the stream contains types that aren't the built-in ones (see \l
+ QMetaType::Type), those types must be registered using qRegisterMetaType()
+ or QMetaType::registerType() before the variant can be properly loaded. If
+ an unregistered type is found, QVariant will set the corrupt flag in the
+ stream, stop processing and print a warning. For example, for QList<int>
+ it would print the following:
+
+ \quotation
+ QVariant::load: unknown user type with name QList<int>
+ \endquotation
+
\sa{Serializing Qt Data Types}{Format of the QDataStream operators}
*/
QDataStream &operator>>(QDataStream &s, QVariant &p)
@@ -1350,6 +1407,7 @@ QDataStream &operator>>(QDataStream &s, QVariant &p)
/*!
Writes a variant \a p to the stream \a s.
+ \relates QVariant
\sa{Serializing Qt Data Types}{Format of the QDataStream operators}
*/
@@ -1360,13 +1418,15 @@ QDataStream &operator<<(QDataStream &s, const QVariant &p)
}
/*! \fn QDataStream& operator>>(QDataStream &s, QVariant::Type &p)
- \deprecated
+ \relates QVariant
+ \deprecated [6.0] Stream QMetaType::Type instead.
Reads a variant type \a p in enum representation from the stream \a s.
*/
/*! \fn QDataStream& operator<<(QDataStream &s, const QVariant::Type p)
- \deprecated
+ \relates QVariant
+ \deprecated [6.0] Stream QMetaType::Type instead.
Writes a variant type \a p to the stream \a s.
*/
@@ -1415,8 +1475,13 @@ QString QVariant::toString() const
}
/*!
- Returns the variant as a QMap<QString, QVariant> if the variant
- has type() \l QMetaType::QVariantMap; otherwise returns an empty map.
+ Returns the variant as a QVariantMap if the variant has type() \l
+ QMetaType::QVariantMap. If it doesn't, QVariant will attempt to
+ convert the type to a map and then return it. This will succeed for
+ any type that has registered a converter to QVariantMap or which was
+ declared as a associative container using
+ \l{Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE}. If none of those
+ conditions are true, this function will return an empty map.
\sa canConvert(), convert()
*/
@@ -1781,6 +1846,7 @@ QChar QVariant::toChar() const
return qvariant_cast<QChar>(*this);
}
+#ifndef QT_BOOTSTRAPPED
/*!
Returns the variant as a QBitArray if the variant has userType()
\l QMetaType::QBitArray; otherwise returns an empty bit array.
@@ -1791,16 +1857,17 @@ QBitArray QVariant::toBitArray() const
{
return qvariant_cast<QBitArray>(*this);
}
+#endif // QT_BOOTSTRAPPED
template <typename T>
-inline T qNumVariantToHelper(const QVariant::Private &d, bool *ok, const T& val)
+inline T qNumVariantToHelper(const QVariant::Private &d, bool *ok)
{
QMetaType t = QMetaType::fromType<T>();
if (ok)
*ok = true;
if (d.type() == t)
- return val;
+ return d.get<T>();
T ret = 0;
bool success = QMetaType::convert(d.type(), d.storage(), t, &ret);
@@ -1828,7 +1895,7 @@ inline T qNumVariantToHelper(const QVariant::Private &d, bool *ok, const T& val)
*/
int QVariant::toInt(bool *ok) const
{
- return qNumVariantToHelper<int>(d, ok, d.get<int>());
+ return qNumVariantToHelper<int>(d, ok);
}
/*!
@@ -1850,7 +1917,7 @@ int QVariant::toInt(bool *ok) const
*/
uint QVariant::toUInt(bool *ok) const
{
- return qNumVariantToHelper<uint>(d, ok, d.get<unsigned int>());
+ return qNumVariantToHelper<uint>(d, ok);
}
/*!
@@ -1867,7 +1934,7 @@ uint QVariant::toUInt(bool *ok) const
*/
qlonglong QVariant::toLongLong(bool *ok) const
{
- return qNumVariantToHelper<qlonglong>(d, ok, d.get<qlonglong>());
+ return qNumVariantToHelper<qlonglong>(d, ok);
}
/*!
@@ -1884,7 +1951,7 @@ qlonglong QVariant::toLongLong(bool *ok) const
*/
qulonglong QVariant::toULongLong(bool *ok) const
{
- return qNumVariantToHelper<qulonglong>(d, ok, d.get<qulonglong>());
+ return qNumVariantToHelper<qulonglong>(d, ok);
}
/*!
@@ -1924,7 +1991,7 @@ bool QVariant::toBool() const
*/
double QVariant::toDouble(bool *ok) const
{
- return qNumVariantToHelper<double>(d, ok, d.get<double>());
+ return qNumVariantToHelper<double>(d, ok);
}
/*!
@@ -1943,7 +2010,7 @@ double QVariant::toDouble(bool *ok) const
*/
float QVariant::toFloat(bool *ok) const
{
- return qNumVariantToHelper<float>(d, ok, d.get<float>());
+ return qNumVariantToHelper<float>(d, ok);
}
/*!
@@ -1962,13 +2029,17 @@ float QVariant::toFloat(bool *ok) const
*/
qreal QVariant::toReal(bool *ok) const
{
- return qNumVariantToHelper<qreal>(d, ok, d.get<qreal>());
+ return qNumVariantToHelper<qreal>(d, ok);
}
/*!
- Returns the variant as a QVariantList if the variant has userType()
- \l QMetaType::QVariantList or \l QMetaType::QStringList; otherwise returns
- an empty list.
+ Returns the variant as a QVariantList if the variant has userType() \l
+ QMetaType::QVariantList. If it doesn't, QVariant will attempt to convert
+ the type to a list and then return it. This will succeed for any type that
+ has registered a converter to QVariantList or which was declared as a
+ sequential container using \l{Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE}. If
+ none of those conditions are true, this function will return an empty
+ list.
\sa canConvert(), convert()
*/
@@ -1980,7 +2051,7 @@ QVariantList QVariant::toList() const
/*!
\fn bool QVariant::canConvert(int targetTypeId) const
\overload
- \deprecated
+ \deprecated [6.0] Use \c canConvert(QMetaType(targetTypeId)) instead.
\sa QMetaType::canConvert()
*/
@@ -1999,7 +2070,7 @@ QVariantList QVariant::toList() const
/*!
\fn bool QVariant::convert(int targetTypeId)
- \deprecated
+ \deprecated [6.0] Use \c convert(QMetaType(targetTypeId)) instead.
Casts the variant to the requested type, \a targetTypeId. If the cast cannot be
done, the variant is still changed to the requested type, but is left in a cleared
@@ -2017,7 +2088,7 @@ QVariantList QVariant::toList() const
failed a previous conversion will always fail, changing the type, remaining null,
and returning \c false.
- \sa canConvert(int targetTypeId), clear()
+ \sa canConvert(), clear()
*/
/*!
@@ -2055,7 +2126,7 @@ bool QVariant::convert(QMetaType targetType)
return false;
// Fail if the value is not initialized or was forced null by a previous failed convert.
- if (oldValue.d.is_null && oldValue.d.typeId() != QMetaType::Nullptr)
+ if (oldValue.d.is_null && oldValue.d.type().id() != QMetaType::Nullptr)
return false;
bool ok = QMetaType::convert(oldValue.d.type(), oldValue.constData(), targetType, data());
@@ -2082,9 +2153,9 @@ bool QVariant::view(int type, void *ptr)
}
/*!
- \fn bool QVariant::operator==(const QVariant &v1, const QVariant &v2)
+ \fn bool QVariant::operator==(const QVariant &lhs, const QVariant &rhs)
- Returns \c true if \a v1 and \a v2 are equal; otherwise returns \c false.
+ Returns \c true if \a lhs and \a rhs are equal; otherwise returns \c false.
QVariant uses the equality operator of the type() contained to check for
equality.
@@ -2108,9 +2179,9 @@ bool QVariant::view(int type, void *ptr)
*/
/*!
- \fn bool QVariant::operator!=(const QVariant &v1, const QVariant &v2)
+ \fn bool QVariant::operator!=(const QVariant &lhs, const QVariant &rhs)
- Returns \c false if \a v1 and \a v2 are equal; otherwise returns \c true.
+ Returns \c false if \a lhs and \a rhs are equal; otherwise returns \c true.
QVariant uses the equality operator of the type() contained to check for
equality.
@@ -2137,6 +2208,8 @@ static bool qIsNumericType(uint tp)
Q_UINT64_C(1) << QMetaType::Double |
Q_UINT64_C(1) << QMetaType::Float |
Q_UINT64_C(1) << QMetaType::Char |
+ Q_UINT64_C(1) << QMetaType::Char16 |
+ Q_UINT64_C(1) << QMetaType::Char32 |
Q_UINT64_C(1) << QMetaType::SChar |
Q_UINT64_C(1) << QMetaType::UChar |
Q_UINT64_C(1) << QMetaType::Short |
@@ -2152,33 +2225,52 @@ static bool qIsNumericType(uint tp)
static bool qIsFloatingPoint(uint tp)
{
- return tp == QMetaType::Double || tp == QMetaType::Float;
+ return tp == QMetaType::Double || tp == QMetaType::Float || tp == QMetaType::Float16;
}
-static int normalizeLowerRanks(uint tp)
+static bool canBeNumericallyCompared(const QtPrivate::QMetaTypeInterface *iface1,
+ const QtPrivate::QMetaTypeInterface *iface2)
{
- static const qulonglong numericTypeBits =
- Q_UINT64_C(1) << QMetaType::Bool |
- Q_UINT64_C(1) << QMetaType::Char |
- Q_UINT64_C(1) << QMetaType::SChar |
- Q_UINT64_C(1) << QMetaType::UChar |
- Q_UINT64_C(1) << QMetaType::Short |
- Q_UINT64_C(1) << QMetaType::UShort;
- return numericTypeBits & (Q_UINT64_C(1) << tp) ? uint(QMetaType::Int) : tp;
-}
+ if (!iface1 || !iface2)
+ return false;
-static int normalizeLong(uint tp)
-{
- const uint IntType = sizeof(long) == sizeof(int) ? QMetaType::Int : QMetaType::LongLong;
- const uint UIntType = sizeof(ulong) == sizeof(uint) ? QMetaType::UInt : QMetaType::ULongLong;
- return tp == QMetaType::Long ? IntType :
- tp == QMetaType::ULong ? UIntType : tp;
+ // We don't need QMetaType::id() here because the type Id is always stored
+ // directly for all built-in types.
+ bool isNumeric1 = qIsNumericType(iface1->typeId);
+ bool isNumeric2 = qIsNumericType(iface2->typeId);
+
+ // if they're both numeric (or QString), then they can be compared
+ if (isNumeric1 && isNumeric2)
+ return true;
+
+ bool isEnum1 = iface1->flags & QMetaType::IsEnumeration;
+ bool isEnum2 = iface2->flags & QMetaType::IsEnumeration;
+
+ // if both are enums, we can only compare if they are the same enum
+ // (the language does allow comparing two different enum types, but that's
+ // usually considered poor coding and produces a warning)
+ if (isEnum1 && isEnum2)
+ return QMetaType(iface1) == QMetaType(iface2);
+
+ // if one is an enum and the other is a numeric, we can compare too
+ if (isEnum1 && isNumeric2)
+ return true;
+ if (isNumeric1 && isEnum2)
+ return true;
+
+ // we need at least one enum and one numeric...
+ return false;
}
-static int numericTypePromotion(uint t1, uint t2)
+static int numericTypePromotion(const QtPrivate::QMetaTypeInterface *iface1,
+ const QtPrivate::QMetaTypeInterface *iface2)
{
- Q_ASSERT(qIsNumericType(t1));
- Q_ASSERT(qIsNumericType(t2));
+ Q_ASSERT(canBeNumericallyCompared(iface1, iface2));
+
+ // We don't need QMetaType::id() here because the type Id is always stored
+ // directly for the types we're comparing against below.
+ uint t1 = iface1->typeId;
+ uint t2 = iface2->typeId;
if ((t1 == QMetaType::Bool && t2 == QMetaType::QString) ||
(t2 == QMetaType::Bool && t1 == QMetaType::QString))
@@ -2202,159 +2294,97 @@ static int numericTypePromotion(uint t1, uint t2)
if (qIsFloatingPoint(t1) || qIsFloatingPoint(t2))
return QMetaType::QReal;
+ auto isUnsigned = [](uint tp) {
+ // only types for which sizeof(T) >= sizeof(int); lesser ones promote to int
+ return tp == QMetaType::ULongLong || tp == QMetaType::ULong ||
+ tp == QMetaType::UInt || tp == QMetaType::Char32;
+ };
+ bool isUnsigned1 = isUnsigned(t1);
+ bool isUnsigned2 = isUnsigned(t2);
+
// integral rules:
- // for all platforms we support, int can always hold the values of lower-ranked types
- t1 = normalizeLowerRanks(t1);
- t2 = normalizeLowerRanks(t2);
-
- // normalize long / ulong: in all platforms we run, they're either the same as int or as long long
- t1 = normalizeLong(t1);
- t2 = normalizeLong(t2);
-
- // implement the other rules
- // the four possibilities are Int, UInt, LongLong and ULongLong
- // if any of the two is ULongLong, then it wins (highest rank, unsigned)
- // otherwise, if one of the two is LongLong, then the other is either LongLong too or lower-ranked
- // otherwise, if one of the two is UInt, then the other is either UInt too or Int
- if (t1 == QMetaType::ULongLong || t2 == QMetaType::ULongLong)
+ // 1) if either type is a 64-bit unsigned, compare as 64-bit unsigned
+ if (isUnsigned1 && iface1->size > sizeof(int))
+ return QMetaType::ULongLong;
+ if (isUnsigned2 && iface2->size > sizeof(int))
return QMetaType::ULongLong;
- if (t1 == QMetaType::LongLong || t2 == QMetaType::LongLong)
+
+ // 2) if either type is 64-bit, compare as 64-bit signed
+ if (iface1->size > sizeof(int) || iface2->size > sizeof(int))
return QMetaType::LongLong;
- if (t1 == QMetaType::UInt || t2 == QMetaType::UInt)
+
+ // 3) if either type is 32-bit unsigned, compare as 32-bit unsigned
+ if (isUnsigned1 || isUnsigned2)
return QMetaType::UInt;
+
+ // 4) otherwise, just do int promotion
return QMetaType::Int;
}
-static bool integralEquals(uint promotedType, const QVariant::Private *d1, const QVariant::Private *d2)
+template <typename Numeric> static QPartialOrdering spaceShip(Numeric lhs, Numeric rhs)
{
- // use toLongLong to retrieve the data, it gets us all the bits
- bool ok;
- qlonglong l1 = qConvertToNumber(d1, &ok, promotedType == QMetaType::Bool);
- if (!ok)
- return false;
-
- qlonglong l2 = qConvertToNumber(d2, &ok, promotedType == QMetaType::Bool);
- if (!ok)
- return false;
-
- if (promotedType == QMetaType::Bool)
- return bool(l1) == bool(l2);
- if (promotedType == QMetaType::Int)
- return int(l1) == int(l2);
- if (promotedType == QMetaType::UInt)
- return uint(l1) == uint(l2);
- if (promotedType == QMetaType::LongLong)
- return l1 == l2;
- if (promotedType == QMetaType::ULongLong)
- return qulonglong(l1) == qulonglong(l2);
-
- Q_UNREACHABLE();
- return 0;
-}
+ if (lhs == rhs)
+ return QPartialOrdering::Equivalent;
+ if constexpr (std::numeric_limits<Numeric>::has_quiet_NaN) {
+ if (std::isnan(lhs) || std::isnan(rhs))
+ return QPartialOrdering::Unordered;
+ }
-namespace {
-template<typename Numeric>
-int spaceShip(Numeric lhs, Numeric rhs)
-{
bool smaller;
if constexpr (std::is_same_v<Numeric, QObject *>)
smaller = std::less<QObject *>()(lhs, rhs); // can't use less all the time because of bool
else
smaller = lhs < rhs;
- if (smaller)
- return -1;
- else if (lhs == rhs)
- return 0;
- else
- return 1;
-}
+ return smaller ? QPartialOrdering::Less : QPartialOrdering::Greater;
}
-static std::optional<int> integralCompare(uint promotedType, const QVariant::Private *d1, const QVariant::Private *d2)
+static QPartialOrdering integralCompare(uint promotedType, const QVariant::Private *d1, const QVariant::Private *d2)
{
// use toLongLong to retrieve the data, it gets us all the bits
- bool ok;
- qlonglong l1 = qConvertToNumber(d1, &ok, promotedType == QMetaType::Bool);
- if (!ok)
- return std::nullopt;
-
- qlonglong l2 = qConvertToNumber(d2, &ok, promotedType == QMetaType::Bool);
- if (!ok)
- return std::nullopt;
-
- if (promotedType == QMetaType::Bool)
- return spaceShip<bool>(l1, l2);
- if (promotedType == QMetaType::Int)
- return spaceShip<int>(l1, l2);
+ std::optional<qlonglong> l1 = qConvertToNumber(d1, promotedType == QMetaType::Bool);
+ std::optional<qlonglong> l2 = qConvertToNumber(d2, promotedType == QMetaType::Bool);
+ if (!l1 || !l2)
+ return QPartialOrdering::Unordered;
if (promotedType == QMetaType::UInt)
- return spaceShip<uint>(l1, l2);
+ return spaceShip<uint>(*l1, *l2);
if (promotedType == QMetaType::LongLong)
- return spaceShip<qlonglong>(l1, l2);
+ return spaceShip<qlonglong>(*l1, *l2);
if (promotedType == QMetaType::ULongLong)
- return spaceShip<qulonglong>(l1, l2);
+ return spaceShip<qulonglong>(*l1, *l2);
- Q_UNREACHABLE();
- return 0;
+ return spaceShip<int>(*l1, *l2);
}
-static std::optional<int> numericCompare(const QVariant::Private *d1, const QVariant::Private *d2)
+static QPartialOrdering numericCompare(const QVariant::Private *d1, const QVariant::Private *d2)
{
- uint promotedType = numericTypePromotion(d1->typeId(), d2->typeId());
+ uint promotedType = numericTypePromotion(d1->typeInterface(), d2->typeInterface());
if (promotedType != QMetaType::QReal)
return integralCompare(promotedType, d1, d2);
- // qreal comparisons
- bool ok;
- qreal r1 = qConvertToRealNumber(d1, &ok);
- if (!ok)
- return std::nullopt;
- qreal r2 = qConvertToRealNumber(d2, &ok);
- if (!ok)
- return std::nullopt;
- if (r1 == r2)
- return 0;
-
- if (std::isnan(r1) || std::isnan(r2))
- return std::nullopt;
- return spaceShip<qreal>(r1, r2);
-}
-static bool numericEquals(const QVariant::Private *d1, const QVariant::Private *d2)
-{
- uint promotedType = numericTypePromotion(d1->typeId(), d2->typeId());
- if (promotedType != QMetaType::QReal)
- return integralEquals(promotedType, d1, d2);
-
- // qreal comparisons
- bool ok;
- qreal r1 = qConvertToRealNumber(d1, &ok);
- if (!ok)
- return false;
- qreal r2 = qConvertToRealNumber(d2, &ok);
- if (!ok)
- return false;
- if (r1 == r2)
- return true;
+ // floating point comparison
+ const auto r1 = qConvertToRealNumber(d1);
+ const auto r2 = qConvertToRealNumber(d2);
+ if (!r1 || !r2)
+ return QPartialOrdering::Unordered;
+ if (*r1 == *r2)
+ return QPartialOrdering::Equivalent;
- return false;
+ return spaceShip(*r1, *r2);
}
#ifndef QT_BOOTSTRAPPED
-static bool canConvertMetaObject(QMetaType fromType, QMetaType toType)
+static bool qvCanConvertMetaObject(QMetaType fromType, QMetaType toType)
{
- if ((fromType.flags() & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) {
- return fromType.metaObject()->inherits(toType.metaObject()) ||
- toType.metaObject()->inherits(fromType.metaObject());
+ if ((fromType.flags() & QMetaType::PointerToQObject)
+ && (toType.flags() & QMetaType::PointerToQObject)) {
+ const QMetaObject *f = fromType.metaObject();
+ const QMetaObject *t = toType.metaObject();
+ return f && t && (f->inherits(t) || t->inherits(f));
}
return false;
}
-static bool pointerEquals(const QVariant::Private *d1, const QVariant::Private *d2)
-{
- // simply check whether both types point to the same data
- return d1->get<QObject *>() == d2->get<QObject *>();
-}
-
-static int pointerCompare(const QVariant::Private *d1, const QVariant::Private *d2)
+static QPartialOrdering pointerCompare(const QVariant::Private *d1, const QVariant::Private *d2)
{
return spaceShip<QObject *>(d1->get<QObject *>(), d2->get<QObject *>());
}
@@ -2369,12 +2399,12 @@ bool QVariant::equals(const QVariant &v) const
if (metatype != v.metaType()) {
// try numeric comparisons, with C++ type promotion rules (no conversion)
- if (qIsNumericType(metatype.id()) && qIsNumericType(v.d.typeId()))
- return numericEquals(&d, &v.d);
+ if (canBeNumericallyCompared(metatype.iface(), v.d.type().iface()))
+ return numericCompare(&d, &v.d) == QPartialOrdering::Equivalent;
#ifndef QT_BOOTSTRAPPED
// if both types are related pointers to QObjects, check if they point to the same object
- if (canConvertMetaObject(metatype, v.metaType()))
- return pointerEquals(&d, &v.d);
+ if (qvCanConvertMetaObject(metatype, v.metaType()))
+ return pointerCompare(&d, &v.d) == QPartialOrdering::Equivalent;
#endif
return false;
}
@@ -2386,18 +2416,6 @@ bool QVariant::equals(const QVariant &v) const
return metatype.equals(d.storage(), v.d.storage());
}
-static QPartialOrdering convertOptionalToPartialOrdering(const std::optional<int> &opt)
-{
- if (!opt)
- return QPartialOrdering::Unordered;
- else if (*opt < 0)
- return QPartialOrdering::Less;
- else if (*opt == 0)
- return QPartialOrdering::Equivalent;
- else
- return QPartialOrdering::Greater;
-}
-
/*!
Compares the objects at \a lhs and \a rhs for ordering.
@@ -2425,11 +2443,11 @@ QPartialOrdering QVariant::compare(const QVariant &lhs, const QVariant &rhs)
QMetaType t = lhs.d.type();
if (t != rhs.d.type()) {
// try numeric comparisons, with C++ type promotion rules (no conversion)
- if (qIsNumericType(lhs.d.typeId()) && qIsNumericType(rhs.d.typeId()))
- return convertOptionalToPartialOrdering(numericCompare(&lhs.d, &rhs.d));
+ if (canBeNumericallyCompared(lhs.d.type().iface(), rhs.d.type().iface()))
+ return numericCompare(&lhs.d, &rhs.d);
#ifndef QT_BOOTSTRAPPED
- if (canConvertMetaObject(lhs.metaType(), rhs.metaType()))
- return convertOptionalToPartialOrdering(pointerCompare(&lhs.d, &rhs.d));
+ if (qvCanConvertMetaObject(lhs.metaType(), rhs.metaType()))
+ return pointerCompare(&lhs.d, &rhs.d);
#endif
return QPartialOrdering::Unordered;
}
@@ -2443,7 +2461,7 @@ QPartialOrdering QVariant::compare(const QVariant &lhs, const QVariant &rhs)
Returns a pointer to the contained object as a generic void* that cannot be
written to.
- \sa QMetaType
+ \sa get_if(), QMetaType
*/
/*!
@@ -2453,7 +2471,7 @@ QPartialOrdering QVariant::compare(const QVariant &lhs, const QVariant &rhs)
This function detaches the QVariant. When called on a \l{isNull}{null-QVariant},
the QVariant will not be null after the call.
- \sa QMetaType
+ \sa get_if(), QMetaType
*/
void *QVariant::data()
{
@@ -2464,6 +2482,42 @@ void *QVariant::data()
}
/*!
+ \since 6.6
+ \fn template <typename T> const T* QVariant::get_if(const QVariant *v)
+ \fn template <typename T> T* QVariant::get_if(QVariant *v)
+
+ If \a v contains an object of type \c T, returns a pointer to the contained
+ object, otherwise returns \nullptr.
+
+ The overload taking a mutable \a v detaches \a v: When called on a
+ \l{isNull()}{null} \a v with matching type \c T, \a v will not be null
+ after the call.
+
+ These functions are provided for compatibility with \c{std::variant}.
+
+ \sa data()
+*/
+
+/*!
+ \since 6.6
+ \fn template <typename T> T &QVariant::get(QVariant &v)
+ \fn template <typename T> const T &QVariant::get(const QVariant &v)
+ \fn template <typename T> T &&QVariant::get(QVariant &&v)
+ \fn template <typename T> const T &&QVariant::get(const QVariant &&v)
+
+ If \a v contains an object of type \c T, returns a reference to the contained
+ object, otherwise the call has undefined behavior.
+
+ The overloads taking a mutable \a v detach \a v: When called on a
+ \l{isNull()}{null} \a v with matching type \c T, \a v will not be null
+ after the call.
+
+ These functions are provided for compatibility with \c{std::variant}.
+
+ \sa get_if(), data()
+*/
+
+/*!
Returns \c true if this is a null variant, false otherwise.
A variant is considered null if it contains no initialized value or a null pointer.
@@ -2487,7 +2541,7 @@ bool QVariant::isNull() const
QDebug QVariant::qdebugHelper(QDebug dbg) const
{
QDebugStateSaver saver(dbg);
- const uint typeId = d.typeId();
+ const uint typeId = d.type().id();
dbg.nospace() << "QVariant(";
if (typeId != QMetaType::UnknownType) {
dbg << d.type().name() << ", ";
@@ -2501,6 +2555,22 @@ QDebug QVariant::qdebugHelper(QDebug dbg) const
return dbg;
}
+QVariant QVariant::moveConstruct(QMetaType type, void *data)
+{
+ QVariant var;
+ var.d = QVariant::Private(type.d_ptr);
+ customConstruct<ForceMove, NonNull>(type.d_ptr, &var.d, data);
+ return var;
+}
+
+QVariant QVariant::copyConstruct(QMetaType type, const void *data)
+{
+ QVariant var;
+ var.d = QVariant::Private(type.d_ptr);
+ customConstruct<UseCopy, NonNull>(type.d_ptr, &var.d, data);
+ return var;
+}
+
#if QT_DEPRECATED_SINCE(6, 0)
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
@@ -2520,7 +2590,7 @@ QT_WARNING_POP
#endif
-/*! \fn template<typename T> void QVariant::setValue(T &&value)
+/*! \fn template<typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, QVariant>>> void QVariant::setValue(T &&value)
Stores a copy of \a value. If \c{T} is a type that QVariant
doesn't support, QMetaType is used to store the value. A compile
@@ -2533,19 +2603,19 @@ QT_WARNING_POP
\sa value(), fromValue(), canConvert()
*/
-/*! \fn template<typename T> void QVariant::setValue(const QVariant &value)
+/*! \fn void QVariant::setValue(const QVariant &value)
Copies \a value over this QVariant. It is equivalent to simply
assigning \a value to this QVariant.
*/
-/*! \fn template<typename T> void QVariant::setValue(QVariant &&value)
+/*! \fn void QVariant::setValue(QVariant &&value)
Moves \a value over this QVariant. It is equivalent to simply
move assigning \a value to this QVariant.
*/
-/*! \fn template<typename T> T QVariant::value() const
+/*! \fn template<typename T> T QVariant::value() const &
Returns the stored value converted to the template type \c{T}.
Call canConvert() to find out whether a type can be converted.
@@ -2585,7 +2655,7 @@ QT_WARNING_POP
\sa canView(), Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE()
*/
-/*! \fn bool QVariant::canConvert() const
+/*! \fn template<typename T> bool QVariant::canConvert() const
Returns \c true if the variant can be converted to the template type \c{T},
otherwise false.
@@ -2601,7 +2671,7 @@ QT_WARNING_POP
\sa convert()
*/
-/*! \fn bool QVariant::canView() const
+/*! \fn template<typename T> bool QVariant::canView() const
Returns \c true if a mutable view of the template type \c{T} can be created on this variant,
otherwise \c false.
@@ -2618,12 +2688,15 @@ QT_WARNING_POP
\snippet code/src_corelib_kernel_qvariant.cpp 7
- \note If you are working with custom types, you should use
- the Q_DECLARE_METATYPE() macro to register your custom type.
-
\sa setValue(), value()
*/
+/*! \fn template<typename T, QVariant::if_rvalue<T> = true> static QVariant QVariant::fromValue(T &&value)
+
+ \since 6.6
+ \overload
+*/
+
/*! \fn template<typename... Types> QVariant QVariant::fromStdVariant(const std::variant<Types...> &value)
\since 5.11
@@ -2638,6 +2711,47 @@ QT_WARNING_POP
*/
/*!
+ \fn template<typename... Types> QVariant QVariant::fromStdVariant(std::variant<Types...> &&value)
+ \since 6.6
+ \overload
+*/
+
+
+/*!
+ \since 6.7
+
+ Creates a variant of type \a type, and initializes it with
+ a copy of \c{*copy} if \a copy is not \nullptr (in which case, \a copy
+ must point to an object of type \a type).
+
+ Note that you have to pass the address of the object you want stored.
+
+ Usually, you never have to use this constructor, use QVariant::fromValue()
+ instead to construct variants from the pointer types represented by
+ \c QMetaType::VoidStar, and \c QMetaType::QObjectStar.
+
+ If \a type does not support copy construction and \a copy is not \nullptr,
+ the variant will be invalid. Similarly, if \a copy is \nullptr and
+ \a type does not support default construction, the variant will be
+ invalid.
+
+ Returns the QVariant created as described above.
+
+ \sa QVariant::fromValue(), QMetaType::Type
+*/
+QVariant QVariant::fromMetaType(QMetaType type, const void *copy)
+{
+ QVariant result;
+ type.registerType();
+ const auto iface = type.iface();
+ if (isValidMetaTypeForVariant(iface, copy)) {
+ result.d = Private(iface);
+ customConstruct(iface, &result.d, copy);
+ }
+ return result;
+}
+
+/*!
\fn template<typename T> T qvariant_cast(const QVariant &value)
\relates QVariant
@@ -2648,6 +2762,14 @@ QT_WARNING_POP
\sa QVariant::value()
*/
+/*!
+ \fn template<typename T> T QVariant::qvariant_cast(QVariant &&value)
+ \overload
+ \since 6.7
+
+ Returns the given \a value converted to the template type \c{T}.
+*/
+
/*! \fn template<typename T> T qVariantValue(const QVariant &value)
\relates QVariant
\deprecated