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.cpp4155
1 files changed, 1127 insertions, 3028 deletions
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 61a80eeae8..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,129 +47,103 @@
#include "qline.h"
#endif
+#include <memory>
+
#include <cmath>
#include <float.h>
#include <cstring>
QT_BEGIN_NAMESPACE
-namespace {
-class HandlersManager
-{
- static const QVariant::Handler *Handlers[QModulesPrivate::ModulesCount];
-public:
- const QVariant::Handler *operator[] (const uint typeId) const
- {
- return Handlers[QModulesPrivate::moduleForType(typeId)];
- }
-
- void registerHandler(const QModulesPrivate::Names name, const QVariant::Handler *handler)
- {
- Handlers[name] = handler;
- }
-};
-} // namespace
-
-namespace {
-struct CoreTypesFilter {
- template<typename T>
- struct Acceptor {
- static const bool IsAccepted = QModulesPrivate::QTypeModuleInfo<T>::IsCore && QtMetaTypePrivate::TypeDefinition<T>::IsAvailable;
- };
-};
-} // annonymous
-
-namespace { // annonymous used to hide QVariant handlers
+using namespace Qt::StringLiterals;
-static bool isNull(const QVariant::Private *d)
-{
- QVariantIsNull<CoreTypesFilter> isNull(d);
- return QMetaTypeSwitcher::switcher<bool>(isNull, d->type().id());
-}
+namespace { // anonymous used to hide QVariant handlers
-/*!
- \internal
-
- Compares \a a to \a b. The caller guarantees that \a a and \a b
- are of the same type.
- */
-static bool compare(const QVariant::Private *a, const QVariant::Private *b)
+static qlonglong qMetaTypeNumberBySize(const QVariant::Private *d)
{
- QVariantComparator<CoreTypesFilter> comparator(a, b);
- return QMetaTypeSwitcher::switcher<bool>(comparator, a->type().id());
+ 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->type().id()) {
+ switch (d->typeInterface()->typeId) {
case QMetaType::Int:
- return d->data.i;
case QMetaType::LongLong:
- return d->data.ll;
case QMetaType::Char:
- return qlonglong(d->data.c);
case QMetaType::SChar:
- return qlonglong(d->data.sc);
case QMetaType::Short:
- return qlonglong(d->data.s);
case QMetaType::Long:
- return qlonglong(d->data.l);
+ return qMetaTypeNumberBySize(d);
case QMetaType::Float:
- return qRound64(d->data.f);
+ return qRound64(d->get<float>());
case QMetaType::Double:
- return qRound64(d->data.d);
+ return qRound64(d->get<double>());
#ifndef QT_BOOTSTRAPPED
case QMetaType::QJsonValue:
- return v_cast<QJsonValue>(d)->toDouble();
+ return d->get<QJsonValue>().toDouble();
case QMetaType::QCborValue:
- return v_cast<QCborValue>(d)->toInteger();
+ return d->get<QCborValue>().toInteger();
#endif
}
- Q_ASSERT(false);
- return 0;
+ Q_UNREACHABLE_RETURN(0);
}
static qulonglong qMetaTypeUNumber(const QVariant::Private *d)
{
- switch (d->type().id()) {
- case QMetaType::UInt:
- return d->data.u;
- case QMetaType::ULongLong:
- return d->data.ull;
- case QMetaType::UChar:
- return d->data.uc;
- case QMetaType::UShort:
- return d->data.us;
- case QMetaType::ULong:
- return d->data.ul;
+ switch (d->typeInterface()->size) {
+ case 1:
+ return d->get<unsigned char>();
+ case 2:
+ return d->get<unsigned short>();
+ 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)
+static std::optional<qlonglong> qConvertToNumber(const QVariant::Private *d, bool allowStringToBool = false)
{
- *ok = true;
-
- switch (uint(d->type().id())) {
- case QMetaType::QString:
- return v_cast<QString>(d)->toLongLong(ok);
+ bool ok;
+ switch (d->typeInterface()->typeId) {
+ case QMetaType::QString: {
+ const QString &s = d->get<QString>();
+ if (qlonglong l = s.toLongLong(&ok); ok)
+ return l;
+ if (allowStringToBool) {
+ if (s == "false"_L1 || s == "0"_L1)
+ return 0;
+ if (s == "true"_L1 || s == "1"_L1)
+ return 1;
+ }
+ return std::nullopt;
+ }
case QMetaType::QChar:
- return v_cast<QChar>(d)->unicode();
+ return d->get<QChar>().unicode();
case QMetaType::QByteArray:
- return v_cast<QByteArray>(d)->toLongLong(ok);
+ if (qlonglong l = d->get<QByteArray>().toLongLong(&ok); ok)
+ return l;
+ return std::nullopt;
case QMetaType::Bool:
- return qlonglong(d->data.b);
+ return qlonglong(d->get<bool>());
#ifndef QT_BOOTSTRAPPED
case QMetaType::QCborValue:
- if (!v_cast<QCborValue>(d)->isInteger() && !v_cast<QCborValue>(d)->isDouble())
+ if (!d->get<QCborValue>().isInteger() && !d->get<QCborValue>().isDouble())
break;
return qMetaTypeNumber(d);
case QMetaType::QJsonValue:
- if (!v_cast<QJsonValue>(d)->isDouble())
+ if (!d->get<QJsonValue>().isDouble())
break;
Q_FALLTHROUGH();
#endif
@@ -221,1318 +159,162 @@ static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok)
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->type().id() == QMetaType::QCborSimpleType) {
- switch (typeInfo.sizeOf()) {
- case 1:
- return d->is_shared ? *reinterpret_cast<signed char *>(d->data.shared->ptr) : d->data.sc;
- case 2:
- return d->is_shared ? *reinterpret_cast<qint16 *>(d->data.shared->ptr) : d->data.s;
- case 4:
- return d->is_shared ? *reinterpret_cast<qint32 *>(d->data.shared->ptr) : d->data.i;
- case 8:
- return d->is_shared ? *reinterpret_cast<qint64 *>(d->data.shared->ptr) : d->data.ll;
- }
- }
+ 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->type().id())) {
+ bool ok;
+ switch (d->typeInterface()->typeId) {
+ case QMetaType::QString:
+ if (double r = d->get<QString>().toDouble(&ok); ok)
+ return r;
+ return std::nullopt;
case QMetaType::Double:
- return qreal(d->data.d);
+ return d->get<double>();
case QMetaType::Float:
- return qreal(d->data.f);
+ 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 v_cast<QCborValue>(d)->toDouble();
+ return d->get<QCborValue>().toDouble();
case QMetaType::QJsonValue:
- return v_cast<QJsonValue>(d)->toDouble();
+ return d->get<QJsonValue>().toDouble();
#endif
default:
// includes enum conversion as well as invalid types
- return qreal(qConvertToNumber(d, ok));
- }
-}
-
-static qulonglong qConvertToUnsignedNumber(const QVariant::Private *d, bool *ok)
-{
- *ok = true;
-
- switch (uint(d->type().id())) {
- case QMetaType::QString:
- return v_cast<QString>(d)->toULongLong(ok);
- case QMetaType::QChar:
- return v_cast<QChar>(d)->unicode();
- case QMetaType::QByteArray:
- return v_cast<QByteArray>(d)->toULongLong(ok);
- case QMetaType::Bool:
- return qulonglong(d->data.b);
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QCborValue:
- if (v_cast<QCborValue>(d)->isDouble())
- return qulonglong(qConvertToRealNumber(d, ok));
- if (!v_cast<QCborValue>(d)->isInteger())
- return false;
- return qulonglong(qMetaTypeNumber(d));
- case QMetaType::QJsonValue:
- if (!v_cast<QJsonValue>(d)->isDouble())
- break;
- Q_FALLTHROUGH();
-#endif
- case QMetaType::Double:
- case QMetaType::Int:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- case QMetaType::Long:
- case QMetaType::Float:
- case QMetaType::LongLong:
- return qulonglong(qMetaTypeNumber(d));
- case QMetaType::ULongLong:
- case QMetaType::UInt:
- case QMetaType::UChar:
- case QMetaType::UShort:
- case QMetaType::ULong:
- return qMetaTypeUNumber(d);
- }
-
- QMetaType typeInfo = d->type();
- if (typeInfo.flags() & QMetaType::IsEnumeration) {
- switch (typeInfo.sizeOf()) {
- case 1:
- return d->is_shared ? *reinterpret_cast<uchar *>(d->data.shared->ptr) : d->data.uc;
- case 2:
- return d->is_shared ? *reinterpret_cast<quint16 *>(d->data.shared->ptr) : d->data.us;
- case 4:
- return d->is_shared ? *reinterpret_cast<quint32 *>(d->data.shared->ptr) : d->data.u;
- case 8:
- return d->is_shared ? *reinterpret_cast<qint64 *>(d->data.shared->ptr) : d->data.ull;
- }
- }
-
- *ok = false;
- return Q_UINT64_C(0);
-}
-
-template<typename TInput, typename LiteralWrapper>
-inline bool qt_convertToBool(const QVariant::Private *const d)
-{
- TInput str = v_cast<TInput>(d)->toLower();
- return !(str.isEmpty() || str == LiteralWrapper("0") || str == LiteralWrapper("false"));
-}
-
-/*!
- \internal
- Returns the internal data pointer from \a d.
- */
-
-static const void *constData(const QVariant::Private &d)
-{
- return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.c);
-}
-
-#ifndef QT_NO_QOBJECT
-/*!
- \internal
- returns a QMetaEnum for a given meta tape type id if possible
-*/
-static QMetaEnum metaEnumFromType(QMetaType t)
-{
- if (t.flags() & QMetaType::IsEnumeration) {
- if (const QMetaObject *metaObject = t.metaObject()) {
- const QByteArray enumName = t.name();
- const char *lastColon = std::strrchr(enumName, ':');
- return metaObject->enumerator(metaObject->indexOfEnumerator(
- lastColon ? lastColon + 1 : enumName.constData()));
- }
+ if (std::optional<qlonglong> l = qConvertToNumber(d))
+ return double(*l);
+ return std::nullopt;
}
- return QMetaEnum();
}
-#endif
-
-/*!
- \internal
- Converts \a d to type \a t, which is placed in \a result.
- */
-static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
+static bool isValidMetaTypeForVariant(const QtPrivate::QMetaTypeInterface *iface, const void *copy)
{
- Q_ASSERT(d->type().id() != t);
- Q_ASSERT(result);
-
- if (d->type().id() >= QMetaType::User || t >= QMetaType::User) {
- const bool isOk = QMetaType::convert(constData(*d), d->type().id(), result, t);
- if (ok)
- *ok = isOk;
- if (isOk)
- return true;
- }
-
- bool dummy;
- if (!ok)
- ok = &dummy;
-
- switch (uint(t)) {
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QUrl:
- switch (d->type().id()) {
- case QMetaType::QString:
- *static_cast<QUrl *>(result) = QUrl(*v_cast<QString>(d));
- break;
- case QMetaType::QCborValue:
- if (v_cast<QCborValue>(d)->isUrl()) {
- *static_cast<QUrl *>(result) = v_cast<QCborValue>(d)->toUrl();
- break;
- }
- return false;
- default:
- return false;
- }
- break;
-#endif // QT_BOOTSTRAPPED
-#if QT_CONFIG(itemmodel)
- case QMetaType::QModelIndex:
- switch (d->type().id()) {
- case QMetaType::QPersistentModelIndex:
- *static_cast<QModelIndex *>(result) = QModelIndex(*v_cast<QPersistentModelIndex>(d));
- break;
- default:
- return false;
- }
- break;
- case QMetaType::QPersistentModelIndex:
- switch (d->type().id()) {
- case QMetaType::QModelIndex:
- *static_cast<QPersistentModelIndex *>(result) = QPersistentModelIndex(*v_cast<QModelIndex>(d));
- break;
- default:
- return false;
- }
- break;
-#endif // QT_CONFIG(itemmodel)
- case QMetaType::QString: {
- QString *str = static_cast<QString *>(result);
- switch (d->type().id()) {
- case QMetaType::QChar:
- *str = *v_cast<QChar>(d);
- break;
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::UChar:
- *str = QChar::fromLatin1(d->data.c);
- break;
- case QMetaType::Short:
- case QMetaType::Long:
- case QMetaType::Int:
- case QMetaType::LongLong:
- *str = QString::number(qMetaTypeNumber(d));
- break;
- case QMetaType::UInt:
- case QMetaType::ULongLong:
- case QMetaType::UShort:
- case QMetaType::ULong:
- *str = QString::number(qMetaTypeUNumber(d));
- break;
- case QMetaType::Float:
- *str = QString::number(d->data.f, 'g', QLocale::FloatingPointShortest);
- break;
- case QMetaType::Double:
- *str = QString::number(d->data.d, 'g', QLocale::FloatingPointShortest);
- break;
-#if QT_CONFIG(datestring)
- case QMetaType::QDate:
- *str = v_cast<QDate>(d)->toString(Qt::ISODate);
- break;
- case QMetaType::QTime:
- *str = v_cast<QTime>(d)->toString(Qt::ISODateWithMs);
- break;
- case QMetaType::QDateTime:
- *str = v_cast<QDateTime>(d)->toString(Qt::ISODateWithMs);
- break;
-#endif
- case QMetaType::Bool:
- *str = d->data.b ? QStringLiteral("true") : QStringLiteral("false");
- break;
- case QMetaType::QByteArray:
- *str = QString::fromUtf8(v_cast<QByteArray>(d)->constData());
- break;
- case QMetaType::QStringList:
- if (v_cast<QStringList>(d)->count() == 1)
- *str = v_cast<QStringList>(d)->at(0);
- break;
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QUrl:
- *str = v_cast<QUrl>(d)->toString();
- break;
- case QMetaType::QJsonValue:
- if (v_cast<QJsonValue>(d)->isString())
- *str = v_cast<QJsonValue>(d)->toString();
- else if (!v_cast<QJsonValue>(d)->isNull())
- return false;
- break;
- case QMetaType::QCborValue:
- if (v_cast<QCborValue>(d)->isContainer() || v_cast<QCborValue>(d)->isTag())
- return false;
- *str = v_cast<QCborValue>(d)->toVariant().toString();
- break;
-#endif
- case QMetaType::QUuid:
- *str = v_cast<QUuid>(d)->toString();
- break;
- case QMetaType::Nullptr:
- *str = QString();
- break;
- default:
-#ifndef QT_NO_QOBJECT
- {
- QMetaEnum en = metaEnumFromType(d->type());
- if (en.isValid()) {
- *str = QString::fromUtf8(en.valueToKey(qConvertToNumber(d, ok)));
- return *ok;
- }
- }
-#endif
- return false;
- }
- break;
- }
- case QMetaType::QChar: {
- QChar *c = static_cast<QChar *>(result);
- switch (d->type().id()) {
- case QMetaType::Int:
- case QMetaType::LongLong:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- case QMetaType::Long:
- case QMetaType::Float:
- *c = QChar::fromUcs2(qMetaTypeNumber(d));
- break;
- case QMetaType::UInt:
- case QMetaType::ULongLong:
- case QMetaType::UChar:
- case QMetaType::UShort:
- case QMetaType::ULong:
- *c = QChar::fromUcs2(qMetaTypeUNumber(d));
- break;
- default:
- return false;
- }
- break;
- }
-#ifndef QT_NO_GEOM_VARIANT
- case QMetaType::QSize: {
- QSize *s = static_cast<QSize *>(result);
- switch (d->type().id()) {
- case QMetaType::QSizeF:
- *s = v_cast<QSizeF>(d)->toSize();
- break;
- default:
- return false;
- }
- break;
- }
-
- case QMetaType::QSizeF: {
- QSizeF *s = static_cast<QSizeF *>(result);
- switch (d->type().id()) {
- case QMetaType::QSize:
- *s = QSizeF(*(v_cast<QSize>(d)));
- break;
- default:
- return false;
- }
- break;
- }
-
- case QMetaType::QLine: {
- QLine *s = static_cast<QLine *>(result);
- switch (d->type().id()) {
- case QMetaType::QLineF:
- *s = v_cast<QLineF>(d)->toLine();
- break;
- default:
- return false;
- }
- break;
- }
-
- case QMetaType::QLineF: {
- QLineF *s = static_cast<QLineF *>(result);
- switch (d->type().id()) {
- case QMetaType::QLine:
- *s = QLineF(*(v_cast<QLine>(d)));
- break;
- default:
- return false;
- }
- break;
- }
-#endif
- case QMetaType::QStringList:
- if (d->type().id() == QMetaType::QVariantList) {
- QStringList *slst = static_cast<QStringList *>(result);
- const QVariantList *list = v_cast<QVariantList >(d);
- const int size = list->size();
- slst->reserve(size);
- for (int i = 0; i < size; ++i)
- slst->append(list->at(i).toString());
- } else if (d->type().id() == QMetaType::QString) {
- QStringList *slst = static_cast<QStringList *>(result);
- *slst = QStringList(*v_cast<QString>(d));
- } else {
- return false;
- }
- break;
- case QMetaType::QDate: {
- QDate *dt = static_cast<QDate *>(result);
- if (d->type().id() == QMetaType::QDateTime)
- *dt = v_cast<QDateTime>(d)->date();
-#if QT_CONFIG(datestring)
- else if (d->type().id() == QMetaType::QString)
- *dt = QDate::fromString(*v_cast<QString>(d), Qt::ISODate);
-#endif
- else
- return false;
-
- return dt->isValid();
- }
- case QMetaType::QTime: {
- QTime *t = static_cast<QTime *>(result);
- switch (d->type().id()) {
- case QMetaType::QDateTime:
- *t = v_cast<QDateTime>(d)->time();
- break;
-#if QT_CONFIG(datestring)
- case QMetaType::QString:
- *t = QTime::fromString(*v_cast<QString>(d), Qt::ISODate);
- break;
-#endif
- default:
- return false;
- }
- return t->isValid();
- }
- case QMetaType::QDateTime: {
- QDateTime *dt = static_cast<QDateTime *>(result);
- switch (d->type().id()) {
-#if QT_CONFIG(datestring)
- case QMetaType::QString:
- *dt = QDateTime::fromString(*v_cast<QString>(d), Qt::ISODate);
- break;
-# ifndef QT_BOOTSTRAPPED
- case QMetaType::QCborValue:
- if (v_cast<QCborValue>(d)->isDateTime())
- *dt = v_cast<QCborValue>(d)->toDateTime();
- else
- return false;
- break;
-# endif
-#endif
- case QMetaType::QDate:
- *dt = v_cast<QDate>(d)->startOfDay();
- break;
- default:
- return false;
- }
- return dt->isValid();
- }
- case QMetaType::QByteArray: {
- QByteArray *ba = static_cast<QByteArray *>(result);
- switch (d->type().id()) {
- case QMetaType::QString:
- *ba = v_cast<QString>(d)->toUtf8();
- break;
- case QMetaType::Double:
- *ba = QByteArray::number(d->data.d, 'g', QLocale::FloatingPointShortest);
- break;
- case QMetaType::Float:
- *ba = QByteArray::number(d->data.f, 'g', QLocale::FloatingPointShortest);
- break;
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::UChar:
- *ba = QByteArray(1, d->data.c);
- break;
- case QMetaType::Int:
- case QMetaType::LongLong:
- case QMetaType::Short:
- case QMetaType::Long:
- *ba = QByteArray::number(qMetaTypeNumber(d));
- break;
- case QMetaType::UInt:
- case QMetaType::ULongLong:
- case QMetaType::UShort:
- case QMetaType::ULong:
- *ba = QByteArray::number(qMetaTypeUNumber(d));
- break;
- case QMetaType::Bool:
- *ba = QByteArray(d->data.b ? "true" : "false");
- break;
- case QMetaType::QUuid:
- *ba = v_cast<QUuid>(d)->toByteArray();
- break;
- case QMetaType::Nullptr:
- *ba = QByteArray();
- break;
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QCborValue:
- if (v_cast<QCborValue>(d)->isByteArray())
- *ba = v_cast<QCborValue>(d)->toByteArray();
- else
- return false;
- break;
-#endif
- default:
-#ifndef QT_NO_QOBJECT
- {
- QMetaEnum en = metaEnumFromType(d->type());
- if (en.isValid()) {
- *ba = en.valueToKey(qConvertToNumber(d, ok));
- return *ok;
- }
- }
-#endif
- return false;
- }
- }
- break;
- case QMetaType::Short:
- *static_cast<short *>(result) = short(qConvertToNumber(d, ok));
- return *ok;
- case QMetaType::Long:
- *static_cast<long *>(result) = long(qConvertToNumber(d, ok));
- return *ok;
- case QMetaType::UShort:
- *static_cast<ushort *>(result) = ushort(qConvertToUnsignedNumber(d, ok));
- return *ok;
- case QMetaType::ULong:
- *static_cast<ulong *>(result) = ulong(qConvertToUnsignedNumber(d, ok));
- return *ok;
- case QMetaType::Int:
- *static_cast<int *>(result) = int(qConvertToNumber(d, ok));
- return *ok;
- case QMetaType::UInt:
- *static_cast<uint *>(result) = uint(qConvertToUnsignedNumber(d, ok));
- return *ok;
- case QMetaType::LongLong:
- *static_cast<qlonglong *>(result) = qConvertToNumber(d, ok);
- return *ok;
- case QMetaType::ULongLong: {
- *static_cast<qulonglong *>(result) = qConvertToUnsignedNumber(d, ok);
- return *ok;
- }
- case QMetaType::SChar: {
- signed char s = qConvertToNumber(d, ok);
- *static_cast<signed char*>(result) = s;
- return *ok;
- }
- case QMetaType::UChar: {
- *static_cast<uchar *>(result) = qConvertToUnsignedNumber(d, ok);
- return *ok;
- }
- case QMetaType::Bool: {
- bool *b = static_cast<bool *>(result);
- switch (d->type().id()) {
- case QMetaType::QByteArray:
- *b = qt_convertToBool<QByteArray, const char*>(d);
- break;
- case QMetaType::QString:
- *b = qt_convertToBool<QString, QLatin1String>(d);
- break;
- case QMetaType::QChar:
- *b = !v_cast<QChar>(d)->isNull();
- break;
- case QMetaType::Double:
- case QMetaType::Int:
- case QMetaType::LongLong:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- case QMetaType::Long:
- case QMetaType::Float:
- *b = qMetaTypeNumber(d) != Q_INT64_C(0);
- break;
- case QMetaType::UInt:
- case QMetaType::ULongLong:
- case QMetaType::UChar:
- case QMetaType::UShort:
- case QMetaType::ULong:
- *b = qMetaTypeUNumber(d) != Q_UINT64_C(0);
- break;
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QCborValue:
- *b = v_cast<QCborValue>(d)->toBool();
- if (!v_cast<QCborValue>(d)->isBool())
- return false;
- break;
- case QMetaType::QJsonValue:
- *b = v_cast<QJsonValue>(d)->toBool(false);
- if (!v_cast<QJsonValue>(d)->isBool())
- return false;
- break;
-#endif
- default:
- *b = false;
- return false;
- }
- break;
- }
- case QMetaType::Double: {
- double *f = static_cast<double *>(result);
- switch (d->type().id()) {
- case QMetaType::QString:
- *f = v_cast<QString>(d)->toDouble(ok);
- break;
- case QMetaType::QByteArray:
- *f = v_cast<QByteArray>(d)->toDouble(ok);
- break;
- case QMetaType::Bool:
- *f = double(d->data.b);
- break;
- case QMetaType::Float:
- *f = double(d->data.f);
- break;
- case QMetaType::LongLong:
- case QMetaType::Int:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- case QMetaType::Long:
- *f = double(qMetaTypeNumber(d));
- break;
- case QMetaType::UInt:
- case QMetaType::ULongLong:
- case QMetaType::UChar:
- case QMetaType::UShort:
- case QMetaType::ULong:
- *f = double(qMetaTypeUNumber(d));
- break;
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QCborValue:
- *f = v_cast<QCborValue>(d)->toDouble();
- if (!v_cast<QCborValue>(d)->isDouble())
- return false;
- break;
- case QMetaType::QJsonValue:
- *f = v_cast<QJsonValue>(d)->toDouble(0.0);
- if (!v_cast<QJsonValue>(d)->isDouble())
- return false;
- break;
-#endif
- default:
- *f = 0.0;
- return false;
- }
- break;
- }
- case QMetaType::Float: {
- float *f = static_cast<float *>(result);
- switch (d->type().id()) {
- case QMetaType::QString:
- *f = v_cast<QString>(d)->toFloat(ok);
- break;
- case QMetaType::QByteArray:
- *f = v_cast<QByteArray>(d)->toFloat(ok);
- break;
- case QMetaType::Bool:
- *f = float(d->data.b);
- break;
- case QMetaType::Double:
- *f = float(d->data.d);
- break;
- case QMetaType::LongLong:
- case QMetaType::Int:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- case QMetaType::Long:
- *f = float(qMetaTypeNumber(d));
- break;
- case QMetaType::UInt:
- case QMetaType::ULongLong:
- case QMetaType::UChar:
- case QMetaType::UShort:
- case QMetaType::ULong:
- *f = float(qMetaTypeUNumber(d));
- break;
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QCborValue:
- *f = v_cast<QCborValue>(d)->toDouble();
- if (!v_cast<QCborValue>(d)->isDouble())
- return false;
- break;
- case QMetaType::QJsonValue:
- *f = v_cast<QJsonValue>(d)->toDouble(0.0);
- if (!v_cast<QJsonValue>(d)->isDouble())
- return false;
- break;
-#endif
- default:
- *f = 0.0f;
- return false;
- }
- break;
- }
- case QMetaType::QVariantList:
- if (d->type().id() == QMetaType::QStringList) {
- QVariantList *lst = static_cast<QVariantList *>(result);
- const QStringList *slist = v_cast<QStringList>(d);
- const int size = slist->size();
- lst->reserve(size);
- for (int i = 0; i < size; ++i)
- lst->append(QVariant(slist->at(i)));
-#ifndef QT_BOOTSTRAPPED
- } else if (d->type().id() == QMetaType::QCborValue) {
- if (!v_cast<QCborValue>(d)->isArray())
- return false;
- *static_cast<QVariantList *>(result) = v_cast<QCborValue>(d)->toArray().toVariantList();
- } else if (d->type().id() == QMetaType::QCborArray) {
- *static_cast<QVariantList *>(result) = v_cast<QCborArray>(d)->toVariantList();
- } else if (d->type().id() == QMetaType::QJsonValue) {
- if (!v_cast<QJsonValue>(d)->isArray())
- return false;
- *static_cast<QVariantList *>(result) = v_cast<QJsonValue>(d)->toArray().toVariantList();
- } else if (d->type().id() == QMetaType::QJsonArray) {
- *static_cast<QVariantList *>(result) = v_cast<QJsonArray>(d)->toVariantList();
-#endif
- } else {
- return false;
- }
- break;
- case QMetaType::QVariantMap:
- if (d->type().id() == QMetaType::QVariantHash) {
- QVariantMap *map = static_cast<QVariantMap *>(result);
- const QVariantHash *hash = v_cast<QVariantHash>(d);
- const auto end = hash->end();
- for (auto it = hash->begin(); it != end; ++it)
- static_cast<QMultiMap<QString, QVariant> *>(map)->insert(it.key(), it.value());
-#ifndef QT_BOOTSTRAPPED
- } else if (d->type().id() == QMetaType::QCborValue) {
- if (!v_cast<QCborValue>(d)->isMap())
- return false;
- *static_cast<QVariantMap *>(result) = v_cast<QCborValue>(d)->toMap().toVariantMap();
- } else if (d->type().id() == QMetaType::QCborMap) {
- *static_cast<QVariantMap *>(result) = v_cast<QCborMap>(d)->toVariantMap();
- } else if (d->type().id() == QMetaType::QJsonValue) {
- if (!v_cast<QJsonValue>(d)->isObject())
- return false;
- *static_cast<QVariantMap *>(result) = v_cast<QJsonValue>(d)->toObject().toVariantMap();
- } else if (d->type().id() == QMetaType::QJsonObject) {
- *static_cast<QVariantMap *>(result) = v_cast<QJsonObject>(d)->toVariantMap();
-#endif
- } else {
- return false;
- }
- break;
- case QMetaType::QVariantHash:
- if (d->type().id() == QMetaType::QVariantMap) {
- QVariantHash *hash = static_cast<QVariantHash *>(result);
- const QVariantMap *map = v_cast<QVariantMap>(d);
- const auto end = map->end();
- for (auto it = map->begin(); it != end; ++it)
- hash->insert(it.key(), it.value());
-#ifndef QT_BOOTSTRAPPED
- } else if (d->type().id() == QMetaType::QCborValue) {
- if (!v_cast<QCborValue>(d)->isMap())
- return false;
- *static_cast<QVariantHash *>(result) = v_cast<QCborValue>(d)->toMap().toVariantHash();
- } else if (d->type().id() == QMetaType::QCborMap) {
- *static_cast<QVariantHash *>(result) = v_cast<QCborMap>(d)->toVariantHash();
- } else if (d->type().id() == QMetaType::QJsonValue) {
- if (!v_cast<QJsonValue>(d)->isObject())
- return false;
- *static_cast<QVariantHash *>(result) = v_cast<QJsonValue>(d)->toObject().toVariantHash();
- } else if (d->type().id() == QMetaType::QJsonObject) {
- *static_cast<QVariantHash *>(result) = v_cast<QJsonObject>(d)->toVariantHash();
-#endif
- } else {
- return false;
- }
- break;
-#ifndef QT_NO_GEOM_VARIANT
- case QMetaType::QRect:
- if (d->type().id() == QMetaType::QRectF)
- *static_cast<QRect *>(result) = (v_cast<QRectF>(d))->toRect();
- else
- return false;
- break;
- case QMetaType::QRectF:
- if (d->type().id() == QMetaType::QRect)
- *static_cast<QRectF *>(result) = *v_cast<QRect>(d);
- else
- return false;
- break;
- case QMetaType::QPointF:
- if (d->type().id() == QMetaType::QPoint)
- *static_cast<QPointF *>(result) = *v_cast<QPoint>(d);
- else
- return false;
- break;
- case QMetaType::QPoint:
- if (d->type().id() == QMetaType::QPointF)
- *static_cast<QPoint *>(result) = (v_cast<QPointF>(d))->toPoint();
- else
- return false;
- break;
- case QMetaType::Char:
- {
- *static_cast<qint8 *>(result) = qint8(qConvertToNumber(d, ok));
- return *ok;
- }
-#endif
- case QMetaType::QUuid:
- switch (d->type().id()) {
- case QMetaType::QString:
- *static_cast<QUuid *>(result) = QUuid(*v_cast<QString>(d));
- break;
- case QMetaType::QByteArray:
- *static_cast<QUuid *>(result) = QUuid(*v_cast<QByteArray>(d));
- break;
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QCborValue:
- if (!v_cast<QCborValue>(d)->isUuid())
- return false;
- *static_cast<QUuid *>(result) = v_cast<QCborValue>(d)->toUuid();
- break;
-#endif
- default:
- return false;
- }
- break;
- case QMetaType::Nullptr:
- *static_cast<std::nullptr_t *>(result) = nullptr;
- if (QMetaType::typeFlags(t) & (QMetaType::PointerToGadget | QMetaType::PointerToQObject)
- || d->type().id() == QMetaType::VoidStar) {
- if (v_cast<const void *>(d) == nullptr)
- break;
- }
-#ifndef QT_BOOTSTRAPPED
- if (d->type().id() == QMetaType::QCborValue && v_cast<QCborValue>(d)->isNull())
- break;
-#endif
+ using namespace QtMetaTypePrivate;
+ if (!iface || iface->size == 0)
return false;
-#ifndef QT_BOOTSTRAPPED
-#if QT_CONFIG(regularexpression)
- case QMetaType::QRegularExpression:
- if (d->type().id() != QMetaType::QCborValue
- || !v_cast<QCborValue>(d)->isRegularExpression())
- return false;
- *static_cast<QRegularExpression *>(result) = v_cast<QCborValue>(d)->toRegularExpression();
- break;
-#endif
- case QMetaType::QJsonValue:
- switch (d->type().id()) {
- case QMetaType::Nullptr:
- *static_cast<QJsonValue *>(result) = QJsonValue(QJsonValue::Null);
- break;
- case QMetaType::Bool:
- *static_cast<QJsonValue *>(result) = QJsonValue(d->data.b);
- break;
- case QMetaType::Int:
- case QMetaType::UInt:
- case QMetaType::Double:
- case QMetaType::Float:
- case QMetaType::ULong:
- case QMetaType::Long:
- case QMetaType::LongLong:
- case QMetaType::ULongLong:
- case QMetaType::UShort:
- case QMetaType::UChar:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- *static_cast<QJsonValue *>(result) = QJsonValue(qConvertToRealNumber(d, ok));
- Q_ASSERT(ok);
- break;
- case QMetaType::QString:
- *static_cast<QJsonValue *>(result) = QJsonValue(*v_cast<QString>(d));
- break;
- case QMetaType::QStringList:
- *static_cast<QJsonValue *>(result) = QJsonValue(QJsonArray::fromStringList(*v_cast<QStringList>(d)));
- break;
- case QMetaType::QVariantList:
- *static_cast<QJsonValue *>(result) = QJsonValue(QJsonArray::fromVariantList(*v_cast<QVariantList>(d)));
- break;
- case QMetaType::QVariantMap:
- *static_cast<QJsonValue *>(result) = QJsonValue(QJsonObject::fromVariantMap(*v_cast<QVariantMap>(d)));
- break;
- case QMetaType::QVariantHash:
- *static_cast<QJsonValue *>(result) = QJsonValue(QJsonObject::fromVariantHash(*v_cast<QVariantHash>(d)));
- break;
- case QMetaType::QJsonObject:
- *static_cast<QJsonValue *>(result) = *v_cast<QJsonObject>(d);
- break;
- case QMetaType::QJsonArray:
- *static_cast<QJsonValue *>(result) = *v_cast<QJsonArray>(d);
- break;
- case QMetaType::QJsonDocument: {
- QJsonDocument doc = *v_cast<QJsonDocument>(d);
- *static_cast<QJsonValue *>(result) = doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object());
- break;
- }
- case QMetaType::QCborValue:
- *static_cast<QJsonValue *>(result) = v_cast<QCborValue>(d)->toJsonValue();
- break;
- case QMetaType::QCborMap:
- *static_cast<QJsonValue *>(result) = v_cast<QCborMap>(d)->toJsonObject();
- break;
- case QMetaType::QCborArray:
- *static_cast<QJsonValue *>(result) = v_cast<QCborArray>(d)->toJsonArray();
- break;
- default:
- *static_cast<QJsonValue *>(result) = QJsonValue(QJsonValue::Undefined);
- return false;
- }
- break;
- case QMetaType::QJsonArray:
- switch (d->type().id()) {
- case QMetaType::QStringList:
- *static_cast<QJsonArray *>(result) = QJsonArray::fromStringList(*v_cast<QStringList>(d));
- break;
- case QMetaType::QVariantList:
- *static_cast<QJsonArray *>(result) = QJsonArray::fromVariantList(*v_cast<QVariantList>(d));
- break;
- case QMetaType::QJsonValue:
- if (!v_cast<QJsonValue>(d)->isArray())
- return false;
- *static_cast<QJsonArray *>(result) = v_cast<QJsonValue>(d)->toArray();
- break;
- case QMetaType::QJsonDocument:
- if (!v_cast<QJsonDocument>(d)->isArray())
- return false;
- *static_cast<QJsonArray *>(result) = v_cast<QJsonDocument>(d)->array();
- break;
- case QMetaType::QCborValue:
- if (!v_cast<QCborValue>(d)->isArray())
- return false;
- *static_cast<QJsonArray *>(result) = v_cast<QCborValue>(d)->toArray().toJsonArray();
- break;
- case QMetaType::QCborArray:
- *static_cast<QJsonArray *>(result) = v_cast<QCborArray>(d)->toJsonArray();
- break;
- default:
- return false;
- }
- break;
- case QMetaType::QJsonObject:
- switch (d->type().id()) {
- case QMetaType::QVariantMap:
- *static_cast<QJsonObject *>(result) = QJsonObject::fromVariantMap(*v_cast<QVariantMap>(d));
- break;
- case QMetaType::QVariantHash:
- *static_cast<QJsonObject *>(result) = QJsonObject::fromVariantHash(*v_cast<QVariantHash>(d));
- break;
- case QMetaType::QJsonValue:
- if (!v_cast<QJsonValue>(d)->isObject())
- return false;
- *static_cast<QJsonObject *>(result) = v_cast<QJsonValue>(d)->toObject();
- break;
- case QMetaType::QJsonDocument:
- if (v_cast<QJsonDocument>(d)->isArray())
- return false;
- *static_cast<QJsonObject *>(result) = v_cast<QJsonDocument>(d)->object();
- break;
- case QMetaType::QCborValue:
- if (!v_cast<QCborValue>(d)->isMap())
- return false;
- *static_cast<QJsonObject *>(result) = v_cast<QCborValue>(d)->toMap().toJsonObject();
- break;
- case QMetaType::QCborMap:
- *static_cast<QJsonObject *>(result) = v_cast<QCborMap>(d)->toJsonObject();
- break;
- default:
- return false;
- }
- break;
- case QMetaType::QCborSimpleType:
- if (d->type().id() == QMetaType::QCborValue && v_cast<QCborValue>(d)->isSimpleType()) {
- *static_cast<QCborSimpleType *>(result) = v_cast<QCborValue>(d)->toSimpleType();
- break;
- }
+ 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;
- case QMetaType::QCborValue:
- switch (d->type().id()) {
- case QMetaType::Nullptr:
- *static_cast<QCborValue *>(result) = QCborValue(QCborValue::Null);
- break;
- case QMetaType::Bool:
- *static_cast<QCborValue *>(result) = QCborValue(d->data.b);
- break;
- case QMetaType::Int:
- case QMetaType::UInt:
- case QMetaType::ULong:
- case QMetaType::Long:
- case QMetaType::LongLong:
- case QMetaType::ULongLong:
- case QMetaType::UShort:
- case QMetaType::UChar:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- *static_cast<QCborValue *>(result) = QCborValue(qConvertToNumber(d, ok));
- Q_ASSERT(ok);
- break;
- case QMetaType::Double:
- case QMetaType::Float:
- *static_cast<QCborValue *>(result) = QCborValue(qConvertToRealNumber(d, ok));
- Q_ASSERT(ok);
- break;
- case QMetaType::QString:
- *static_cast<QCborValue *>(result) = *v_cast<QString>(d);
- break;
- case QMetaType::QStringList:
- *static_cast<QCborValue *>(result) = QCborArray::fromStringList(*v_cast<QStringList>(d));
- break;
- case QMetaType::QByteArray:
- *static_cast<QCborValue *>(result) = *v_cast<QByteArray>(d);
- break;
- case QMetaType::QDate:
- *static_cast<QCborValue *>(result) = QCborValue(v_cast<QDate>(d)->startOfDay());
- break;
- case QMetaType::QDateTime:
- *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QDateTime>(d));
- break;
- case QMetaType::QUrl:
- *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QUrl>(d));
- break;
-#if QT_CONFIG(regularexpression)
- case QMetaType::QRegularExpression:
- *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QRegularExpression>(d));
- break;
-#endif
- case QMetaType::QUuid:
- *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QUuid>(d));
- break;
- case QMetaType::QVariantList:
- *static_cast<QCborValue *>(result) = QCborArray::fromVariantList(*v_cast<QVariantList>(d));
- break;
- case QMetaType::QVariantMap:
- *static_cast<QCborValue *>(result) = QCborMap::fromVariantMap(*v_cast<QVariantMap>(d));
- break;
- case QMetaType::QVariantHash:
- *static_cast<QCborValue *>(result) = QCborMap::fromVariantHash(*v_cast<QVariantHash>(d));
- break;
- case QMetaType::QJsonValue:
- *static_cast<QCborValue *>(result) = QCborValue::fromJsonValue(*v_cast<QJsonValue>(d));
- break;
- case QMetaType::QJsonObject:
- *static_cast<QCborValue *>(result) = QCborMap::fromJsonObject(*v_cast<QJsonObject>(d));
- break;
- case QMetaType::QJsonArray:
- *static_cast<QCborValue *>(result) = QCborArray::fromJsonArray(*v_cast<QJsonArray>(d));
- break;
- case QMetaType::QJsonDocument: {
- QJsonDocument doc = *v_cast<QJsonDocument>(d);
- if (doc.isArray())
- *static_cast<QCborValue *>(result) = QCborArray::fromJsonArray(doc.array());
- else
- *static_cast<QCborValue *>(result) = QCborMap::fromJsonObject(doc.object());
- break;
- }
- case QMetaType::QCborSimpleType:
- *static_cast<QCborValue *>(result) = *v_cast<QCborSimpleType>(d);
- break;
- case QMetaType::QCborMap:
- *static_cast<QCborValue *>(result) = *v_cast<QCborMap>(d);
- break;
- case QMetaType::QCborArray:
- *static_cast<QCborValue *>(result) = *v_cast<QCborArray>(d);
- break;
- default:
- *static_cast<QCborValue *>(result) = {};
- return false;
- }
- break;
- case QMetaType::QCborArray:
- switch (d->type().id()) {
- case QMetaType::QStringList:
- *static_cast<QCborArray *>(result) = QCborArray::fromStringList(*v_cast<QStringList>(d));
- break;
- case QMetaType::QVariantList:
- *static_cast<QCborArray *>(result) = QCborArray::fromVariantList(*v_cast<QVariantList>(d));
- break;
- case QMetaType::QCborValue:
- if (!v_cast<QCborValue>(d)->isArray())
- return false;
- *static_cast<QCborArray *>(result) = v_cast<QCborValue>(d)->toArray();
- break;
- case QMetaType::QJsonDocument:
- if (!v_cast<QJsonDocument>(d)->isArray())
- return false;
- *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(v_cast<QJsonDocument>(d)->array());
- break;
- case QMetaType::QJsonValue:
- if (!v_cast<QJsonValue>(d)->isArray())
- return false;
- *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(v_cast<QJsonValue>(d)->toArray());
- break;
- case QMetaType::QJsonArray:
- *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(*v_cast<QJsonArray>(d));
- break;
- default:
- return false;
- }
- break;
- case QMetaType::QCborMap:
- switch (d->type().id()) {
- case QMetaType::QVariantMap:
- *static_cast<QCborMap *>(result) = QCborMap::fromVariantMap(*v_cast<QVariantMap>(d));
- break;
- case QMetaType::QVariantHash:
- *static_cast<QCborMap *>(result) = QCborMap::fromVariantHash(*v_cast<QVariantHash>(d));
- break;
- case QMetaType::QCborValue:
- if (!v_cast<QCborValue>(d)->isMap())
- return false;
- *static_cast<QCborMap *>(result) = v_cast<QCborValue>(d)->toMap();
- break;
- case QMetaType::QJsonDocument:
- if (v_cast<QJsonDocument>(d)->isArray())
- return false;
- *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(v_cast<QJsonDocument>(d)->object());
- break;
- case QMetaType::QJsonValue:
- if (!v_cast<QJsonValue>(d)->isObject())
- return false;
- *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(v_cast<QJsonValue>(d)->toObject());
- break;
- case QMetaType::QJsonObject:
- *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(*v_cast<QJsonObject>(d));
- break;
- default:
- return false;
- }
- break;
-#endif
-
- default:
-#ifndef QT_NO_QOBJECT
- if (d->type().id() == QMetaType::QString || d->type().id() == QMetaType::QByteArray) {
- QMetaEnum en = metaEnumFromType(QMetaType(t));
- if (en.isValid()) {
- QByteArray keys = (d->type().id() == QMetaType::QString)
- ? v_cast<QString>(d)->toUtf8()
- : *v_cast<QByteArray>(d);
- int value = en.keysToValue(keys.constData(), ok);
- if (*ok) {
- switch (QMetaType::sizeOf(t)) {
- case 1:
- *static_cast<signed char *>(result) = value;
- return true;
- case 2:
- *static_cast<qint16 *>(result) = value;
- return true;
- case 4:
- *static_cast<qint32 *>(result) = value;
- return true;
- case 8:
- *static_cast<qint64 *>(result) = value;
- return true;
- }
- }
- }
- }
-#endif
- if (QMetaType::typeFlags(t) & QMetaType::IsEnumeration
- || d->type().id() == QMetaType::QCborSimpleType) {
- qlonglong value = qConvertToNumber(d, ok);
- if (*ok) {
- switch (QMetaType::sizeOf(t)) {
- case 1:
- *static_cast<signed char *>(result) = value;
- return true;
- case 2:
- *static_cast<qint16 *>(result) = value;
- return true;
- case 4:
- *static_cast<qint32 *>(result) = value;
- return true;
- case 8:
- *static_cast<qint64 *>(result) = value;
- return true;
- }
- }
- return *ok;
- }
+ }
+ 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;
-}
-#if !defined(QT_NO_DEBUG_STREAM)
-static void streamDebug(QDebug dbg, const QVariant &v)
-{
- QVariant::Private *d = const_cast<QVariant::Private *>(&v.data_ptr());
- QVariantDebugStream<CoreTypesFilter> stream(dbg, d);
- QMetaTypeSwitcher::switcher<void>(stream, d->type().id());
+ return true;
}
-#endif
-const QVariant::Handler qt_kernel_variant_handler = {
- isNull,
- compare,
- convert,
-#if !defined(QT_NO_DEBUG_STREAM)
- streamDebug
-#else
- nullptr
-#endif
+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)
};
-static bool dummyIsNull(const QVariant::Private *d) { Q_ASSERT_X(false, "QVariant::isNull", "Trying to call isNull on an unknown type"); return d->is_null; }
-static bool dummyCompare(const QVariant::Private *, const QVariant::Private *) { Q_ASSERT_X(false, "QVariant", "Trying to compare an unknown types"); return false; }
-static bool dummyConvert(const QVariant::Private *, int, void *, bool *) { Q_ASSERT_X(false, "QVariant", "Trying to convert an unknown type"); return false; }
-#if !defined(QT_NO_DEBUG_STREAM)
-static void dummyStreamDebug(QDebug, const QVariant &) { Q_ASSERT_X(false, "QVariant", "Trying to convert an unknown type"); }
-#endif
-const QVariant::Handler qt_dummy_variant_handler = {
- dummyIsNull,
- dummyCompare,
- dummyConvert,
-#if !defined(QT_NO_DEBUG_STREAM)
- dummyStreamDebug
-#else
- nullptr
-#endif
+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
-static void customConstruct(QVariant::Private *d, const void *copy)
-{
- const QMetaType type = d->type();
- const uint size = type.sizeOf();
- if (!size) {
- *d = QVariant::Private();
- return;
- }
-
- // this logic should match with QVariantIntegrator::CanUseInternalSpace
- if (size <= sizeof(QVariant::Private::Data)
- && (type.flags() & (QMetaType::MovableType | QMetaType::IsEnumeration))) {
- type.construct(&d->data, copy);
+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)) {
d->is_shared = false;
+ 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
+ construct(iface, d->data.data, copy);
} else {
- // Private::Data contains long long, and long double is the biggest standard type.
- const size_t maxAlignment =
- qMax(alignof(QVariant::Private::Data), alignof(long double));
- const size_t s = sizeof(QVariant::PrivateShared);
- const size_t offset = s + ((s * maxAlignment - s) % maxAlignment);
- void *data = operator new(offset + size);
- void *ptr = static_cast<char *>(data) + offset;
- type.construct(ptr, copy);
+ 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;
- d->data.shared = new (data) QVariant::PrivateShared(ptr);
}
- d->is_null = !copy;
}
static void customClear(QVariant::Private *d)
{
+ const QtPrivate::QMetaTypeInterface *iface = d->typeInterface();
+ if (!iface)
+ return;
if (!d->is_shared) {
- d->type().destruct(&d->data);
+ QtMetaTypePrivate::destruct(iface, d->data.data);
} else {
- d->type().destruct(d->data.shared->ptr);
- d->data.shared->~PrivateShared();
- operator delete(d->data.shared);
- }
-}
-
-static bool customIsNull(const QVariant::Private *d)
-{
- if (d->is_null)
- return true;
- if (d->type().flags() & QMetaType::IsPointer) {
- const void *d_ptr = d->is_shared ? d->data.shared->ptr : &(d->data);
- return *static_cast<void *const *>(d_ptr) == nullptr;
+ QtMetaTypePrivate::destruct(iface, d->data.shared->data());
+ QVariant::PrivateShared::free(d->data.shared);
}
- return false;
}
-static bool customCompare(const QVariant::Private *a, const QVariant::Private *b)
+static QVariant::Private clonePrivate(const QVariant::Private &other)
{
- const void *a_ptr = a->is_shared ? a->data.shared->ptr : &(a->data);
- const void *b_ptr = b->is_shared ? b->data.shared->ptr : &(b->data);
-
- if (a->is_null && b->is_null)
- return true;
-
- return !memcmp(a_ptr, b_ptr, a->type().sizeOf());
-}
+ 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));
-static bool customConvert(const QVariant::Private *d, int t, void *result, bool *ok)
-{
- if (d->type().id() >= QMetaType::User || t >= QMetaType::User) {
- if (QMetaType::convert(constData(*d), d->type().id(), result, t)) {
- if (ok)
- *ok = true;
- return true;
- }
+ // if not trivially copyable, ask to copy
+ if (iface->copyCtr)
+ QtMetaTypePrivate::copyConstruct(iface, d.data.data, other.data.data);
}
- return convert(d, t, result, ok);
-}
-
-#if !defined(QT_NO_DEBUG_STREAM)
-static void customStreamDebug(QDebug dbg, const QVariant &variant) {
-#ifndef QT_BOOTSTRAPPED
- QMetaType::TypeFlags flags = QMetaType::typeFlags(variant.userType());
- if (flags & QMetaType::PointerToQObject)
- dbg.nospace() << qvariant_cast<QObject*>(variant);
-#else
- Q_UNUSED(dbg);
- Q_UNUSED(variant);
-#endif
-}
-#endif
-
-const QVariant::Handler qt_custom_variant_handler = {
- customIsNull,
- customCompare,
- customConvert,
-#if !defined(QT_NO_DEBUG_STREAM)
- customStreamDebug
-#else
- nullptr
-#endif
-};
-
-} // annonymous used to hide QVariant handlers
-
-static HandlersManager handlerManager;
-
-static_assert(!QModulesPrivate::Core, "Initialization assumes that ModulesNames::Core is 0");
-const QVariant::Handler *HandlersManager::Handlers[QModulesPrivate::ModulesCount]
- = { &qt_kernel_variant_handler, &qt_dummy_variant_handler,
- &qt_dummy_variant_handler, &qt_custom_variant_handler };
-
-Q_CORE_EXPORT const QVariant::Handler *qcoreVariantHandler()
-{
- return &qt_kernel_variant_handler;
+ return d;
}
-Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names */name, const QVariant::Handler *handler)
-{
- handlerManager.registerHandler(static_cast<QModulesPrivate::Names>(name), handler);
-}
+} // anonymous used to hide QVariant handlers
/*!
\class QVariant
@@ -1542,17 +324,18 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names
\ingroup objectmodel
\ingroup shared
+ \compares equality
Because C++ forbids unions from including types that have
non-default constructors or destructors, most interesting Qt
classes cannot be used in unions. Without QVariant, this would be
a problem for QObject::property() and for database work, etc.
- A QVariant object holds a single value of a single type() at a
- time. (Some type()s are multi-valued, for example a string list.)
+ A QVariant object holds a single value of a single typeId() at a
+ time. (Some types are multi-valued, for example a string list.)
You can find out what type, T, the variant holds, convert it to a
different type using convert(), get its value using one of the
- toT() functions (e.g., toSize()) and check whether the type can
+ toT() functions (e.g., toSize()), and check whether the type can
be converted to a particular type using canConvert().
The methods named toT() (e.g., toInt(), toString()) are const. If
@@ -1573,15 +356,14 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names
and versatile, but may prove less memory and speed efficient than
storing specific types in standard data structures.
- QVariant also supports the notion of null values, where you can
- have a defined type with no value set. However, note that QVariant
- types can only be cast when they have had a value set.
+ QVariant also supports the notion of null values. A variant is null
+ if the variant contains no initialized value, or contains a null pointer.
\snippet code/src_corelib_kernel_qvariant.cpp 1
QVariant can be extended to support other types than those
- mentioned in the \l Type enum. See \l{Creating Custom Qt Types}{Creating Custom Qt Types}
- for details.
+ mentioned in the \l QMetaType::Type enum.
+ See \l{Creating Custom Qt Types}{Creating Custom Qt Types} for details.
\section1 A Note on GUI Types
@@ -1607,9 +389,9 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names
QVariant to convert between types given suitable data; it is still
possible to supply data which cannot actually be converted.
- For example, canConvert(Int) would return true when called on a variant
- containing a string because, in principle, QVariant is able to convert
- strings of numbers to integers.
+ For example, \c{canConvert(QMetaType::fromType<int>())} would return true
+ when called on a variant containing a string because, in principle,
+ QVariant is able to convert strings of numbers to integers.
However, if the string contains non-numeric characters, it cannot be
converted to an integer, and any attempt to convert it will fail.
Hence, it is important to have both functions return true for a
@@ -1619,7 +401,7 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names
*/
/*!
- \obsolete 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
@@ -1640,7 +422,7 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names
\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
@@ -1712,63 +494,41 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names
Constructs an invalid variant.
*/
-
/*!
- \fn QVariant::QVariant(int typeId, const void *copy)
-
- Constructs variant of type \a typeId, and initializes with
- \a copy if \a copy is not \nullptr.
-
- Note that you have to pass the address of the variable 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
-*/
+ \fn QVariant::create(int type, const void *copy)
-/*!
- \fn QVariant::QVariant(Type type)
+ \internal
- 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
- constructed value of the \a type.
+ Constructs a variant private of type \a type, and initializes with \a copy if
+ \a copy is not \nullptr.
- \sa isNull()
*/
-
-
+//### Qt 7: Remove in favor of QMetaType overload
+void QVariant::create(int type, const void *copy)
+{
+ create(QMetaType(type), copy);
+}
/*!
\fn QVariant::create(int type, const void *copy)
\internal
-
- Constructs a variant private of type \a type, and initializes with \a copy if
- \a copy is not \nullptr.
+ \overload
*/
-
-void QVariant::create(int type, const void *copy)
+void QVariant::create(QMetaType type, const void *copy)
{
- d = Private(QMetaType(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);
}
@@ -1780,37 +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();
- } else if (d.type().isValid()) {
- customConstruct(&d, p.constData());
- d.is_null = p.d.is_null;
- }
}
-#ifndef QT_NO_DATASTREAM
/*!
- Reads the variant from the data stream, \a s.
+ \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(QDataStream &s)
+
+QVariant::QVariant(std::in_place_t, QMetaType type) : d(type.iface())
{
- d.is_null = true;
- s >> *this;
+ // 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;
+ }
+}
+
+/*!
+ \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());
}
-#endif //QT_NO_DATASTREAM
/*!
- \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.
*/
/*!
@@ -1829,37 +673,37 @@ QVariant::QVariant(QDataStream &s)
*/
/*!
- \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.
*/
@@ -1873,14 +717,14 @@ QVariant::QVariant(QDataStream &s)
/*!
\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.
*/
@@ -1921,299 +765,247 @@ QVariant::QVariant(QDataStream &s)
*/
/*!
- \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
Constructs a new variant with the regular expression value \a re.
*/
-QVariant::QVariant(Type type)
-{ create(type, nullptr); }
+/*! \fn QVariant::QVariant(Type type)
+ \deprecated [6.0] Use the constructor taking a QMetaType instead.
-/*!
- \internal
- flags is true if it is a pointer type
- */
-QVariant::QVariant(int typeId, const void *copy, uint flags)
-{
- if (flags) { //type is a pointer type
- d = Private(QMetaType(typeId));
- d.data.ptr = *reinterpret_cast<void *const*>(copy);
- } else {
- create(typeId, copy);
- }
- d.is_null = false;
-}
+ 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
+ constructed value of the \a type.
+
+ \sa isNull()
+*/
/*!
- \internal
- flags is true if it is a pointer type
- */
-QVariant::QVariant(QMetaType type, const void *copy) : d(type)
+ 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 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.
+
+ \sa QVariant::fromMetaType, QVariant::fromValue(), QMetaType::Type
+*/
+QVariant::QVariant(QMetaType type, const void *copy)
+ : d()
{
- customConstruct(&d, copy);
- d.is_null = false;
+ *this = fromMetaType(type, copy);
}
-QVariant::QVariant(int val)
- : d(Int)
-{ d.data.i = val; }
-QVariant::QVariant(uint val)
- : d(UInt)
-{ d.data.u = val; }
-QVariant::QVariant(qlonglong val)
- : d(LongLong)
-{ d.data.ll = val; }
-QVariant::QVariant(qulonglong val)
- : d(ULongLong)
-{ d.data.ull = val; }
-QVariant::QVariant(bool val)
- : d(Bool)
-{ d.data.b = val; }
-QVariant::QVariant(double val)
- : d(Double)
-{ d.data.d = val; }
-QVariant::QVariant(float val)
- : d(QMetaType::Float)
-{ d.data.f = val; }
-
-QVariant::QVariant(const QByteArray &val)
- : d(ByteArray)
-{ v_construct<QByteArray>(&d, val); }
-QVariant::QVariant(const QBitArray &val)
- : d(BitArray)
-{ v_construct<QBitArray>(&d, val); }
-QVariant::QVariant(const QString &val)
- : d(String)
-{ v_construct<QString>(&d, val); }
-QVariant::QVariant(QChar val)
- : d(Char)
-{ v_construct<QChar>(&d, val); }
-QVariant::QVariant(QLatin1String val)
- : d(String)
-{ v_construct<QString>(&d, val); }
-QVariant::QVariant(const QStringList &val)
- : d(StringList)
-{ v_construct<QStringList>(&d, val); }
-
-QVariant::QVariant(QDate val)
- : d(Date)
-{ v_construct<QDate>(&d, val); }
-QVariant::QVariant(QTime val)
- : d(Time)
-{ v_construct<QTime>(&d, val); }
-QVariant::QVariant(const QDateTime &val)
- : d(DateTime)
-{ v_construct<QDateTime>(&d, val); }
+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(EasingCurve)
-{ v_construct<QEasingCurve>(&d, val); }
+QVariant::QVariant(const QEasingCurve &val) : d(std::piecewise_construct_t{}, val) {}
#endif
-QVariant::QVariant(const QList<QVariant> &list)
- : d(List)
-{ v_construct<QVariantList>(&d, list); }
-QVariant::QVariant(const QMap<QString, QVariant> &map)
- : d(Map)
-{ v_construct<QVariantMap>(&d, map); }
-QVariant::QVariant(const QHash<QString, QVariant> &hash)
- : d(Hash)
-{ v_construct<QVariantHash>(&d, hash); }
#ifndef QT_NO_GEOM_VARIANT
-QVariant::QVariant(const QPoint &pt)
- : d(Point)
-{ v_construct<QPoint>(&d, pt); }
-QVariant::QVariant(const QPointF &pt)
- : d(PointF)
-{ v_construct<QPointF>(&d, pt); }
-QVariant::QVariant(const QRectF &r)
- : d(RectF)
-{ v_construct<QRectF>(&d, r); }
-QVariant::QVariant(const QLineF &l)
- : d(LineF)
-{ v_construct<QLineF>(&d, l); }
-QVariant::QVariant(const QLine &l)
- : d(Line)
-{ v_construct<QLine>(&d, l); }
-QVariant::QVariant(const QRect &r)
- : d(Rect)
-{ v_construct<QRect>(&d, r); }
-QVariant::QVariant(const QSize &s)
- : d(Size)
-{ v_construct<QSize>(&d, s); }
-QVariant::QVariant(const QSizeF &s)
- : d(SizeF)
-{ 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(Url)
-{ v_construct<QUrl>(&d, u); }
+QVariant::QVariant(const QUrl &u) noexcept : d(std::piecewise_construct_t{}, u) {}
#endif
-QVariant::QVariant(const QLocale &l)
- : d(Locale)
-{ 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(RegularExpression)
-{ 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(Uuid)
-{ 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::QJsonValue)
-{ v_construct<QJsonValue>(&d, jsonValue); }
-QVariant::QVariant(const QJsonObject &jsonObject)
- : d(QMetaType::QJsonObject)
-{ v_construct<QJsonObject>(&d, jsonObject); }
-QVariant::QVariant(const QJsonArray &jsonArray)
- : d(QMetaType::QJsonArray)
-{ v_construct<QJsonArray>(&d, jsonArray); }
-QVariant::QVariant(const QJsonDocument &jsonDocument)
- : d(QMetaType::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(ModelIndex)
-{ v_construct<QModelIndex>(&d, modelIndex); }
-QVariant::QVariant(const QPersistentModelIndex &modelIndex)
- : d(PersistentModelIndex)
-{ 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 [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,
the return value should be interpreted as QMetaType::Type. In
@@ -2246,23 +1038,19 @@ QVariant::QVariant(const QPersistentModelIndex &modelIndex)
\sa userType(), metaType()
*/
-QVariant::Type QVariant::type() const
-{
- int type = d.type().id();
- return type >= QMetaType::User ? UserType : static_cast<Type>(type);
-}
-/*!
- Returns the storage type of the value stored in the variant. For
- non-user types, this is the same as type().
- \sa type(), metaType()
+/*! \fn int QVariant::userType() const
+ \fn int QVariant::typeId() const
+
+ Returns the storage type of the value stored in the variant. This is
+ the same as metaType().id().
+
+ \sa metaType()
*/
-int QVariant::userType() const
-{
- return d.type().id();
-}
/*!
+ \since 6.0
+
Returns the QMetaType of the value stored in the variant.
*/
QMetaType QVariant::metaType() const
@@ -2273,21 +1061,13 @@ QMetaType QVariant::metaType() const
/*!
Assigns the value of the variant \a variant to this variant.
*/
-QVariant& QVariant::operator=(const QVariant &variant)
+QVariant &QVariant::operator=(const QVariant &variant)
{
if (this == &variant)
return *this;
clear();
- if (variant.d.is_shared) {
- variant.d.data.shared->ref.ref();
- d = variant.d;
- } else {
- d = variant.d;
- customConstruct(&d, reinterpret_cast<const void *>(&variant.d.data));
- d.is_null = variant.d.is_null;
- }
-
+ d = clonePrivate(variant.d);
return *this;
}
@@ -2310,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;
@@ -2331,8 +1113,7 @@ void QVariant::detach()
*/
const char *QVariant::typeName() const
{
- // Cannot use d.type().name because we must return a char*
- return QMetaType::typeName(d.type().id());
+ return d.type().name();
}
/*!
@@ -2341,35 +1122,31 @@ 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 [6.0] Use \c QMetaType(typeId).name() instead.
+
Converts the int representation of the storage type, \a typeId, to
its string representation.
Returns \nullptr if the type is QMetaType::UnknownType or doesn't exist.
*/
-const char *QVariant::typeToName(int typeId)
-{
- return QMetaType::typeName(typeId);
-}
-
/*!
+ \fn QVariant::Type QVariant::nameToType(const char *name)
+ \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.
If the string representation cannot be converted to any enum
representation, the variant is set to \c Invalid.
*/
-QVariant::Type QVariant::nameToType(const char *name)
-{
- int metaType = QMetaType::type(name);
- return metaType <= int(UserType) ? QVariant::Type(metaType) : UserType;
-}
#ifndef QT_NO_DATASTREAM
enum { MapFromThreeCount = 36 };
@@ -2419,6 +1196,18 @@ static const ushort mapIdFromQt3ToCurrent[MapFromThreeCount] =
#endif
};
+// values needed to map Qt5 based type id's to Qt6 based ones
+constexpr int Qt5UserType = 1024;
+constexpr int Qt5LastCoreType = QMetaType::QCborMap;
+constexpr int Qt5FirstGuiType = 64;
+constexpr int Qt5LastGuiType = 87;
+constexpr int Qt5SizePolicy = 121;
+constexpr int Qt5RegExp = 27;
+constexpr int Qt5KeySequence = 75;
+constexpr int Qt5QQuaternion = 85;
+
+constexpr int Qt6ToQt5GuiTypeDelta = qToUnderlying(QMetaType::FirstGuiType) - Qt5FirstGuiType;
+
/*!
Internal function for loading a variant from stream \a s. Use the
stream operators instead.
@@ -2432,35 +1221,46 @@ void QVariant::load(QDataStream &s)
quint32 typeId;
s >> typeId;
if (s.version() < QDataStream::Qt_4_0) {
+ // map to Qt 5 ids
if (typeId >= MapFromThreeCount)
return;
typeId = mapIdFromQt3ToCurrent[typeId];
} else if (s.version() < QDataStream::Qt_5_0) {
+ // map to Qt 5 type ids
if (typeId == 127 /* QVariant::UserType */) {
- typeId = QMetaType::User;
- } else if (typeId >= 128 && typeId != QVariant::UserType) {
+ typeId = Qt5UserType;
+ } else if (typeId >= 128 && typeId != Qt5UserType) {
// In Qt4 id == 128 was FirstExtCoreType. In Qt5 ExtCoreTypes set was merged to CoreTypes
// by moving all ids down by 97.
typeId -= 97;
} else if (typeId == 75 /* QSizePolicy */) {
- typeId = QMetaType::QSizePolicy;
+ typeId = Qt5SizePolicy;
} else if (typeId > 75 && typeId <= 86) {
// and as a result these types received lower ids too
// QKeySequence QPen QTextLength QTextFormat QTransform QMatrix4x4 QVector2D QVector3D QVector4D QQuaternion
typeId -=1;
}
}
+ if (s.version() < QDataStream::Qt_6_0) {
+ // map from Qt 5 to Qt 6 values
+ if (typeId == Qt5UserType) {
+ typeId = QMetaType::User;
+ } else if (typeId >= Qt5FirstGuiType && typeId <= Qt5LastGuiType) {
+ typeId += Qt6ToQt5GuiTypeDelta;
+ } else if (typeId == Qt5SizePolicy) {
+ typeId = QMetaType::QSizePolicy;
+ } else if (typeId == Qt5RegExp) {
+ typeId = QMetaType::fromName("QRegExp").id();
+ }
+ }
qint8 is_null = false;
if (s.version() >= QDataStream::Qt_4_2)
s >> is_null;
- if (typeId == 27) {
- // used to be QRegExp in Qt 4/5
- typeId = QMetaType::type("QRegExp");
- } else if (typeId == QVariant::UserType) {
+ if (typeId == QMetaType::User) {
QByteArray name;
s >> name;
- typeId = QMetaType::type(name.constData());
+ typeId = QMetaType::fromName(name).id();
if (typeId == QMetaType::UnknownType) {
s.setStatus(QDataStream::ReadCorruptData);
qWarning("QVariant::load: unknown user type with name %s.", name.constData());
@@ -2472,7 +1272,7 @@ void QVariant::load(QDataStream &s)
if (!isValid()) {
if (s.version() < QDataStream::Qt_5_0) {
- // Since we wrote something, we should read something
+ // Since we wrote something, we should read something
QString x;
s >> x;
}
@@ -2481,7 +1281,8 @@ void QVariant::load(QDataStream &s)
}
// const cast is safe since we operate on a newly constructed variant
- if (!QMetaType::load(s, d.type().id(), const_cast<void *>(constData()))) {
+ 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.type().id());
}
@@ -2501,6 +1302,27 @@ void QVariant::save(QDataStream &s) const
typeId = QMetaType::User;
saveAsUserType = true;
}
+ if (s.version() < QDataStream::Qt_6_0) {
+ // map to Qt 5 values
+ if (typeId == QMetaType::User) {
+ typeId = Qt5UserType;
+ if (!strcmp(d.type().name(), "QRegExp")) {
+ typeId = 27; // QRegExp in Qt 4/5
+ }
+ } else if (typeId > Qt5LastCoreType && typeId <= QMetaType::LastCoreType) {
+ // the type didn't exist in Qt 5
+ typeId = Qt5UserType;
+ saveAsUserType = true;
+ } else if (typeId >= QMetaType::FirstGuiType && typeId <= QMetaType::LastGuiType) {
+ typeId -= Qt6ToQt5GuiTypeDelta;
+ if (typeId > Qt5LastGuiType) {
+ typeId = Qt5UserType;
+ saveAsUserType = true;
+ }
+ } else if (typeId == QMetaType::QSizePolicy) {
+ typeId = Qt5SizePolicy;
+ }
+ }
if (s.version() < QDataStream::Qt_4_0) {
int i;
for (i = 0; i <= MapFromThreeCount - 1; ++i) {
@@ -2514,23 +1336,19 @@ void QVariant::save(QDataStream &s) const
return;
}
} else if (s.version() < QDataStream::Qt_5_0) {
- if (typeId == QMetaType::User) {
+ if (typeId == Qt5UserType) {
typeId = 127; // QVariant::UserType had this value in Qt4
saveAsUserType = true;
- } else if (typeId >= 128 - 97 && typeId <= LastCoreType) {
+ } else if (typeId >= 128 - 97 && typeId <= Qt5LastCoreType) {
// In Qt4 id == 128 was FirstExtCoreType. In Qt5 ExtCoreTypes set was merged to CoreTypes
// by moving all ids down by 97.
typeId += 97;
- } else if (typeId == QMetaType::QSizePolicy) {
+ } else if (typeId == Qt5SizePolicy) {
typeId = 75;
-#if QT_CONFIG(shortcut)
- } else if (typeId >= QMetaType::QKeySequence && typeId <= QMetaType::QQuaternion) {
-#else
- } else if (typeId >= QMetaType::QPen && typeId <= QMetaType::QQuaternion) {
-#endif
+ } else if (typeId >= Qt5KeySequence && typeId <= Qt5QQuaternion) {
// and as a result these types received lower ids too
- typeId +=1;
- } else if (typeId == QMetaType::QPolygonF || typeId == QMetaType::QUuid) {
+ typeId += 1;
+ } else if (typeId > Qt5QQuaternion || typeId == QMetaType::QUuid) {
// These existed in Qt 4 only as a custom type
typeId = 127;
saveAsUserType = true;
@@ -2538,17 +1356,16 @@ void QVariant::save(QDataStream &s) const
}
const char *typeName = nullptr;
if (saveAsUserType) {
- typeName = QMetaType::typeName(d.type().id());
- if (!strcmp(typeName, "QRegExp")) {
- typeId = 27; // QRegExp in Qt 4/5
- typeName = nullptr;
- }
+ 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 << QMetaType::typeName(userType());
+ s << typeName;
if (!isValid()) {
if (s.version() < QDataStream::Qt_5_0)
@@ -2556,21 +1373,33 @@ void QVariant::save(QDataStream &s) const
return;
}
- if (!QMetaType::save(s, d.type().id(), constData())) {
+ if (!d.type().save(s, constData())) {
qWarning("QVariant::save: unable to save type '%s' (type id: %d).\n",
- QMetaType::typeName(d.type().id()), d.type().id());
+ 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)
+QDataStream &operator>>(QDataStream &s, QVariant &p)
{
p.load(s);
return s;
@@ -2578,37 +1407,29 @@ 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}
*/
-QDataStream& operator<<(QDataStream &s, const QVariant &p)
+QDataStream &operator<<(QDataStream &s, const QVariant &p)
{
p.save(s);
return s;
}
-/*!
+/*! \fn QDataStream& operator>>(QDataStream &s, QVariant::Type &p)
+ \relates QVariant
+ \deprecated [6.0] Stream QMetaType::Type instead.
+
Reads a variant type \a p in enum representation from the stream \a s.
*/
-QDataStream& operator>>(QDataStream &s, QVariant::Type &p)
-{
- quint32 u;
- s >> u;
- p = (QVariant::Type)u;
- return s;
-}
+/*! \fn QDataStream& operator<<(QDataStream &s, const QVariant::Type p)
+ \relates QVariant
+ \deprecated [6.0] Stream QMetaType::Type instead.
-/*!
Writes a variant type \a p to the stream \a s.
*/
-QDataStream& operator<<(QDataStream &s, const QVariant::Type p)
-{
- s << static_cast<quint32>(p);
-
- return s;
-}
-
#endif //QT_NO_DATASTREAM
/*!
@@ -2618,24 +1439,6 @@ QDataStream& operator<<(QDataStream &s, const QVariant::Type p)
QMetaType::UnknownType; otherwise returns \c false.
*/
-template<typename T>
-inline T qVariantToHelper(const QVariant::Private &d)
-{
- QMetaType targetType = QMetaType::fromType<T>();
- if (d.type() == targetType)
- return *v_cast<T>(&d);
-
- T ret;
- if (d.type().id() >= QMetaType::User || targetType.id() >= QMetaType::User) {
- const void * const from = constData(d);
- if (QMetaType::convert(from, d.type().id(), &ret, targetType.id()))
- return ret;
- }
-
- handlerManager[d.type().id()]->convert(&d, targetType.id(), &ret, nullptr);
- return ret;
-}
-
/*!
\fn QStringList QVariant::toStringList() const
@@ -2644,11 +1447,11 @@ inline T qVariantToHelper(const QVariant::Private &d)
\l QMetaType::QVariantList of a type that can be converted to QString;
otherwise returns an empty list.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QStringList QVariant::toStringList() const
{
- return qVariantToHelper<QStringList>(d);
+ return qvariant_cast<QStringList>(*this);
}
/*!
@@ -2664,33 +1467,38 @@ QStringList QVariant::toStringList() const
Calling QVariant::toString() on an unsupported variant returns an empty
string.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QString QVariant::toString() const
{
- return qVariantToHelper<QString>(d);
+ return qvariant_cast<QString>(*this);
}
/*!
- 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(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QVariantMap QVariant::toMap() const
{
- return qVariantToHelper<QVariantMap>(d);
+ return qvariant_cast<QVariantMap>(*this);
}
/*!
Returns the variant as a QHash<QString, QVariant> if the variant
has type() \l QMetaType::QVariantHash; otherwise returns an empty map.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QVariantHash QVariant::toHash() const
{
- return qVariantToHelper<QVariantHash>(d);
+ return qvariant_cast<QVariantHash>(*this);
}
/*!
@@ -2703,11 +1511,11 @@ QVariantHash QVariant::toHash() const
If the type() is \l QMetaType::QString, an invalid date will be returned if
the string cannot be parsed as a Qt::ISODate format date.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QDate QVariant::toDate() const
{
- return qVariantToHelper<QDate>(d);
+ return qvariant_cast<QDate>(*this);
}
/*!
@@ -2720,11 +1528,11 @@ QDate QVariant::toDate() const
If the type() is \l QMetaType::QString, an invalid time will be returned if
the string cannot be parsed as a Qt::ISODate format time.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QTime QVariant::toTime() const
{
- return qVariantToHelper<QTime>(d);
+ return qvariant_cast<QTime>(*this);
}
/*!
@@ -2737,11 +1545,11 @@ QTime QVariant::toTime() const
If the type() is \l QMetaType::QString, an invalid date/time will be
returned if the string cannot be parsed as a Qt::ISODate format date/time.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QDateTime QVariant::toDateTime() const
{
- return qVariantToHelper<QDateTime>(d);
+ return qvariant_cast<QDateTime>(*this);
}
/*!
@@ -2751,12 +1559,12 @@ QDateTime QVariant::toDateTime() const
Returns the variant as a QEasingCurve if the variant has userType()
\l QMetaType::QEasingCurve; otherwise returns a default easing curve.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
#if QT_CONFIG(easingcurve)
QEasingCurve QVariant::toEasingCurve() const
{
- return qVariantToHelper<QEasingCurve>(d);
+ return qvariant_cast<QEasingCurve>(*this);
}
#endif
@@ -2767,11 +1575,11 @@ QEasingCurve QVariant::toEasingCurve() const
\l QMetaType::QByteArray or \l QMetaType::QString (converted using
QString::fromUtf8()); otherwise returns an empty byte array.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QByteArray QVariant::toByteArray() const
{
- return qVariantToHelper<QByteArray>(d);
+ return qvariant_cast<QByteArray>(*this);
}
#ifndef QT_NO_GEOM_VARIANT
@@ -2782,11 +1590,11 @@ QByteArray QVariant::toByteArray() const
\l QMetaType::QPoint or \l QMetaType::QPointF; otherwise returns a null
QPoint.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QPoint QVariant::toPoint() const
{
- return qVariantToHelper<QPoint>(d);
+ return qvariant_cast<QPoint>(*this);
}
/*!
@@ -2795,11 +1603,11 @@ QPoint QVariant::toPoint() const
Returns the variant as a QRect if the variant has userType()
\l QMetaType::QRect; otherwise returns an invalid QRect.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QRect QVariant::toRect() const
{
- return qVariantToHelper<QRect>(d);
+ return qvariant_cast<QRect>(*this);
}
/*!
@@ -2808,11 +1616,11 @@ QRect QVariant::toRect() const
Returns the variant as a QSize if the variant has userType()
\l QMetaType::QSize; otherwise returns an invalid QSize.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QSize QVariant::toSize() const
{
- return qVariantToHelper<QSize>(d);
+ return qvariant_cast<QSize>(*this);
}
/*!
@@ -2821,11 +1629,11 @@ QSize QVariant::toSize() const
Returns the variant as a QSizeF if the variant has userType() \l
QMetaType::QSizeF; otherwise returns an invalid QSizeF.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QSizeF QVariant::toSizeF() const
{
- return qVariantToHelper<QSizeF>(d);
+ return qvariant_cast<QSizeF>(*this);
}
/*!
@@ -2835,11 +1643,11 @@ QSizeF QVariant::toSizeF() const
\l QMetaType::QRect or \l QMetaType::QRectF; otherwise returns an invalid
QRectF.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QRectF QVariant::toRectF() const
{
- return qVariantToHelper<QRectF>(d);
+ return qvariant_cast<QRectF>(*this);
}
/*!
@@ -2848,11 +1656,11 @@ QRectF QVariant::toRectF() const
Returns the variant as a QLineF if the variant has userType()
\l QMetaType::QLineF; otherwise returns an invalid QLineF.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QLineF QVariant::toLineF() const
{
- return qVariantToHelper<QLineF>(d);
+ return qvariant_cast<QLineF>(*this);
}
/*!
@@ -2861,11 +1669,11 @@ QLineF QVariant::toLineF() const
Returns the variant as a QLine if the variant has userType()
\l QMetaType::QLine; otherwise returns an invalid QLine.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QLine QVariant::toLine() const
{
- return qVariantToHelper<QLine>(d);
+ return qvariant_cast<QLine>(*this);
}
/*!
@@ -2875,11 +1683,11 @@ QLine QVariant::toLine() const
QMetaType::QPoint or \l QMetaType::QPointF; otherwise returns a null
QPointF.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QPointF QVariant::toPointF() const
{
- return qVariantToHelper<QPointF>(d);
+ return qvariant_cast<QPointF>(*this);
}
#endif // QT_NO_GEOM_VARIANT
@@ -2891,11 +1699,11 @@ QPointF QVariant::toPointF() const
Returns the variant as a QUrl if the variant has userType()
\l QMetaType::QUrl; otherwise returns an invalid QUrl.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QUrl QVariant::toUrl() const
{
- return qVariantToHelper<QUrl>(d);
+ return qvariant_cast<QUrl>(*this);
}
#endif
@@ -2905,11 +1713,11 @@ QUrl QVariant::toUrl() const
Returns the variant as a QLocale if the variant has userType()
\l QMetaType::QLocale; otherwise returns an invalid QLocale.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QLocale QVariant::toLocale() const
{
- return qVariantToHelper<QLocale>(d);
+ return qvariant_cast<QLocale>(*this);
}
#if QT_CONFIG(regularexpression)
@@ -2920,11 +1728,11 @@ QLocale QVariant::toLocale() const
Returns the variant as a QRegularExpression if the variant has userType() \l
QRegularExpression; otherwise returns an empty QRegularExpression.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QRegularExpression QVariant::toRegularExpression() const
{
- return qVariantToHelper<QRegularExpression>(d);
+ return qvariant_cast<QRegularExpression>(*this);
}
#endif // QT_CONFIG(regularexpression)
@@ -2935,11 +1743,11 @@ QRegularExpression QVariant::toRegularExpression() const
Returns the variant as a QModelIndex if the variant has userType() \l
QModelIndex; otherwise returns a default constructed QModelIndex.
- \sa canConvert(int targetTypeId), convert(), toPersistentModelIndex()
+ \sa canConvert(), convert(), toPersistentModelIndex()
*/
QModelIndex QVariant::toModelIndex() const
{
- return qVariantToHelper<QModelIndex>(d);
+ return qvariant_cast<QModelIndex>(*this);
}
/*!
@@ -2948,11 +1756,11 @@ QModelIndex QVariant::toModelIndex() const
Returns the variant as a QPersistentModelIndex if the variant has userType() \l
QPersistentModelIndex; otherwise returns a default constructed QPersistentModelIndex.
- \sa canConvert(int targetTypeId), convert(), toModelIndex()
+ \sa canConvert(), convert(), toModelIndex()
*/
QPersistentModelIndex QVariant::toPersistentModelIndex() const
{
- return qVariantToHelper<QPersistentModelIndex>(d);
+ return qvariant_cast<QPersistentModelIndex>(*this);
}
#endif // QT_CONFIG(itemmodel)
@@ -2963,11 +1771,11 @@ QPersistentModelIndex QVariant::toPersistentModelIndex() const
\l QMetaType::QUuid, \l QMetaType::QByteArray or \l QMetaType::QString;
otherwise returns a default-constructed QUuid.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QUuid QVariant::toUuid() const
{
- return qVariantToHelper<QUuid>(d);
+ return qvariant_cast<QUuid>(*this);
}
#ifndef QT_BOOTSTRAPPED
@@ -2977,11 +1785,11 @@ QUuid QVariant::toUuid() const
Returns the variant as a QJsonValue if the variant has userType() \l
QJsonValue; otherwise returns a default constructed QJsonValue.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QJsonValue QVariant::toJsonValue() const
{
- return qVariantToHelper<QJsonValue>(d);
+ return qvariant_cast<QJsonValue>(*this);
}
/*!
@@ -2990,11 +1798,11 @@ QJsonValue QVariant::toJsonValue() const
Returns the variant as a QJsonObject if the variant has userType() \l
QJsonObject; otherwise returns a default constructed QJsonObject.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QJsonObject QVariant::toJsonObject() const
{
- return qVariantToHelper<QJsonObject>(d);
+ return qvariant_cast<QJsonObject>(*this);
}
/*!
@@ -3003,11 +1811,11 @@ QJsonObject QVariant::toJsonObject() const
Returns the variant as a QJsonArray if the variant has userType() \l
QJsonArray; otherwise returns a default constructed QJsonArray.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QJsonArray QVariant::toJsonArray() const
{
- return qVariantToHelper<QJsonArray>(d);
+ return qvariant_cast<QJsonArray>(*this);
}
/*!
@@ -3016,11 +1824,11 @@ QJsonArray QVariant::toJsonArray() const
Returns the variant as a QJsonDocument if the variant has userType() \l
QJsonDocument; otherwise returns a default constructed QJsonDocument.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QJsonDocument QVariant::toJsonDocument() const
{
- return qVariantToHelper<QJsonDocument>(d);
+ return qvariant_cast<QJsonDocument>(*this);
}
#endif // QT_BOOTSTRAPPED
@@ -3031,42 +1839,40 @@ QJsonDocument QVariant::toJsonDocument() const
\l QMetaType::QChar, \l QMetaType::Int, or \l QMetaType::UInt; otherwise
returns an invalid QChar.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QChar QVariant::toChar() const
{
- return qVariantToHelper<QChar>(d);
+ 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.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QBitArray QVariant::toBitArray() const
{
- return qVariantToHelper<QBitArray>(d);
+ return qvariant_cast<QBitArray>(*this);
}
+#endif // QT_BOOTSTRAPPED
template <typename T>
-inline T qNumVariantToHelper(const QVariant::Private &d,
- const HandlersManager &handlerManager, bool *ok, const T& val)
+inline T qNumVariantToHelper(const QVariant::Private &d, bool *ok)
{
- const uint t = qMetaTypeId<T>();
+ QMetaType t = QMetaType::fromType<T>();
if (ok)
*ok = true;
- if (d.type().id() == t)
- return val;
+ if (d.type() == t)
+ return d.get<T>();
T ret = 0;
- if ((d.type().id() >= QMetaType::User || t >= QMetaType::User)
- && QMetaType::convert(constData(d), d.type().id(), &ret, t))
- return ret;
-
- if (!handlerManager[d.type().id()]->convert(&d, t, &ret, ok) && ok)
- *ok = false;
+ bool success = QMetaType::convert(d.type(), d.storage(), t, &ret);
+ if (ok)
+ *ok = success;
return ret;
}
@@ -3085,11 +1891,11 @@ inline T qNumVariantToHelper(const QVariant::Private &d,
will not be reflected in \a ok. A simple workaround is to use
QString::toInt().
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
int QVariant::toInt(bool *ok) const
{
- return qNumVariantToHelper<int>(d, handlerManager, ok, d.data.i);
+ return qNumVariantToHelper<int>(d, ok);
}
/*!
@@ -3107,11 +1913,11 @@ int QVariant::toInt(bool *ok) const
overflow will not be reflected in \a ok. A simple workaround is to use
QString::toUInt().
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
uint QVariant::toUInt(bool *ok) const
{
- return qNumVariantToHelper<uint>(d, handlerManager, ok, d.data.u);
+ return qNumVariantToHelper<uint>(d, ok);
}
/*!
@@ -3124,11 +1930,11 @@ uint QVariant::toUInt(bool *ok) const
If \a ok is non-null: \c{*}\c{ok} is set to true if the value could be
converted to an int; otherwise \c{*}\c{ok} is set to false.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
qlonglong QVariant::toLongLong(bool *ok) const
{
- return qNumVariantToHelper<qlonglong>(d, handlerManager, ok, d.data.ll);
+ return qNumVariantToHelper<qlonglong>(d, ok);
}
/*!
@@ -3141,11 +1947,11 @@ qlonglong QVariant::toLongLong(bool *ok) const
If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
converted to an int; otherwise \c{*}\a{ok} is set to false.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
qulonglong QVariant::toULongLong(bool *ok) const
{
- return qNumVariantToHelper<qulonglong>(d, handlerManager, ok, d.data.ull);
+ return qNumVariantToHelper<qulonglong>(d, ok);
}
/*!
@@ -3158,16 +1964,16 @@ qulonglong QVariant::toULongLong(bool *ok) const
\l QMetaType::QByteArray and its lower-case content is not one of the
following: empty, "0" or "false"; otherwise returns \c false.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
bool QVariant::toBool() const
{
- if (d.type() == QMetaType::fromType<bool>())
- return d.data.b;
+ auto boolType = QMetaType::fromType<bool>();
+ if (d.type() == boolType)
+ return d.get<bool>();
bool res = false;
- handlerManager[d.type().id()]->convert(&d, Bool, &res, nullptr);
-
+ QMetaType::convert(d.type(), constData(), boolType, &res);
return res;
}
@@ -3181,11 +1987,11 @@ bool QVariant::toBool() const
If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
converted to a double; otherwise \c{*}\a{ok} is set to false.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
double QVariant::toDouble(bool *ok) const
{
- return qNumVariantToHelper<double>(d, handlerManager, ok, d.data.d);
+ return qNumVariantToHelper<double>(d, ok);
}
/*!
@@ -3200,11 +2006,11 @@ double QVariant::toDouble(bool *ok) const
If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
converted to a double; otherwise \c{*}\a{ok} is set to false.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
float QVariant::toFloat(bool *ok) const
{
- return qNumVariantToHelper<float>(d, handlerManager, ok, d.data.f);
+ return qNumVariantToHelper<float>(d, ok);
}
/*!
@@ -3219,451 +2025,74 @@ float QVariant::toFloat(bool *ok) const
If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
converted to a double; otherwise \c{*}\a{ok} is set to false.
- \sa canConvert(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
qreal QVariant::toReal(bool *ok) const
{
- return qNumVariantToHelper<qreal>(d, handlerManager, ok, d.data.real);
+ 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(int targetTypeId), convert()
+ \sa canConvert(), convert()
*/
QVariantList QVariant::toList() const
{
- return qVariantToHelper<QVariantList>(d);
+ return qvariant_cast<QVariantList>(*this);
}
+/*!
+ \fn bool QVariant::canConvert(int targetTypeId) const
+ \overload
+ \deprecated [6.0] Use \c canConvert(QMetaType(targetTypeId)) instead.
-static const quint32 qCanConvertMatrix[QMetaType::LastCoreType + 1] =
-{
-/*Invalid*/ 0,
-
-/*Bool*/ 1 << QMetaType::Double | 1 << QMetaType::Int | 1 << QMetaType::UInt
- | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong | 1 << QMetaType::QByteArray
- | 1 << QMetaType::QString | 1 << QMetaType::QChar,
-
-/*Int*/ 1 << QMetaType::UInt | 1 << QMetaType::QString | 1 << QMetaType::Double
- | 1 << QMetaType::Bool | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong
- | 1 << QMetaType::QChar | 1 << QMetaType::QByteArray | 1 << QMetaType::Int,
-
-/*UInt*/ 1 << QMetaType::Int | 1 << QMetaType::QString | 1 << QMetaType::Double
- | 1 << QMetaType::Bool | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong
- | 1 << QMetaType::QChar | 1 << QMetaType::QByteArray,
-
-/*LLong*/ 1 << QMetaType::Int | 1 << QMetaType::QString | 1 << QMetaType::Double
- | 1 << QMetaType::Bool | 1 << QMetaType::UInt | 1 << QMetaType::ULongLong
- | 1 << QMetaType::QChar | 1 << QMetaType::QByteArray,
-
-/*ULlong*/ 1 << QMetaType::Int | 1 << QMetaType::QString | 1 << QMetaType::Double
- | 1 << QMetaType::Bool | 1 << QMetaType::UInt | 1 << QMetaType::LongLong
- | 1 << QMetaType::QChar | 1 << QMetaType::QByteArray,
-
-/*double*/ 1 << QMetaType::Int | 1 << QMetaType::QString | 1 << QMetaType::ULongLong
- | 1 << QMetaType::Bool | 1 << QMetaType::UInt | 1 << QMetaType::LongLong
- | 1 << QMetaType::QByteArray,
-
-/*QChar*/ 1 << QMetaType::Int | 1 << QMetaType::UInt | 1 << QMetaType::LongLong
- | 1 << QMetaType::ULongLong,
-
-/*QMap*/ 0,
-
-/*QList*/ 1 << QMetaType::QStringList,
-
-/*QString*/ 1 << QMetaType::QStringList | 1 << QMetaType::QByteArray | 1 << QMetaType::Int
- | 1 << QMetaType::UInt | 1 << QMetaType::Bool | 1 << QMetaType::Double
- | 1 << QMetaType::QDate | 1 << QMetaType::QTime | 1 << QMetaType::QDateTime
- | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong | 1 << QMetaType::QChar
- | 1 << QMetaType::QUrl | 1 << QMetaType::QUuid,
-
-/*QStringList*/ 1 << QMetaType::QVariantList | 1 << QMetaType::QString,
-
-/*QByteArray*/ 1 << QMetaType::QString | 1 << QMetaType::Int | 1 << QMetaType::UInt | 1 << QMetaType::Bool
- | 1 << QMetaType::Double | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong
- | 1 << QMetaType::QUuid,
-
-/*QBitArray*/ 0,
-
-/*QDate*/ 1 << QMetaType::QString | 1 << QMetaType::QDateTime,
-
-/*QTime*/ 1 << QMetaType::QString | 1 << QMetaType::QDateTime,
-
-/*QDateTime*/ 1 << QMetaType::QString | 1 << QMetaType::QDate,
-
-/*QUrl*/ 1 << QMetaType::QString,
-
-/*QLocale*/ 0,
-
-/*QRect*/ 1 << QMetaType::QRectF,
-
-/*QRectF*/ 1 << QMetaType::QRect,
-
-/*QSize*/ 1 << QMetaType::QSizeF,
-
-/*QSizeF*/ 1 << QMetaType::QSize,
-
-/*QLine*/ 1 << QMetaType::QLineF,
-
-/*QLineF*/ 1 << QMetaType::QLine,
-
-/*QPoint*/ 1 << QMetaType::QPointF,
-
-/*QPointF*/ 1 << QMetaType::QPoint,
-
-/*unused, was: QRegExp*/ 0,
-
-/*QHash*/ 0,
-
-/*QEasingCurve*/ 0,
-
-/*QUuid*/ 1 << QMetaType::QString | 1 << QMetaType::QByteArray,
-};
-static const size_t qCanConvertMatrixMaximumTargetType = 8 * sizeof(*qCanConvertMatrix);
-
-#ifndef QT_BOOTSTRAPPED
-/*
- Returns \c true if from inherits to.
+ \sa QMetaType::canConvert()
*/
-static bool canConvertMetaObject(const QMetaObject *from, const QMetaObject *to)
-{
- if (from && to == &QObject::staticMetaObject)
- return true;
-
- while (from) {
- if (from == to)
- return true;
- from = from->superClass();
- }
-
- return false;
-}
-#endif
-
-static bool canConvertMetaObject(int fromId, int toId, QObject *fromObject)
-{
-#ifndef QT_BOOTSTRAPPED
- QMetaType toType(toId);
- if ((QMetaType::typeFlags(fromId) & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) {
- if (!fromObject)
- return true;
- return canConvertMetaObject(fromObject->metaObject(), toType.metaObject());
- }
-#else
- Q_UNUSED(fromId);
- Q_UNUSED(toId);
- Q_UNUSED(fromObject);
-#endif
- return false;
-}
-
/*!
+ \fn bool QVariant::canConvert(QMetaType type) const
+ \since 6.0
+
Returns \c true if the variant's type can be cast to the requested
- type, \a targetTypeId. Such casting is done automatically when calling the
+ type, \a type. Such casting is done automatically when calling the
toInt(), toBool(), ... methods.
- The following casts are done automatically:
-
- \table
- \header \li Type \li Automatically Cast To
- \row \li \l QMetaType::Bool \li \l QMetaType::QChar, \l QMetaType::Double,
- \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString,
- \l QMetaType::UInt, \l QMetaType::ULongLong
- \row \li \l QMetaType::QByteArray \li \l QMetaType::Double,
- \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString,
- \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid
- \row \li \l QMetaType::QChar \li \l QMetaType::Bool, \l QMetaType::Int,
- \l QMetaType::UInt, \l QMetaType::LongLong, \l QMetaType::ULongLong
- \row \li \l QMetaType::QColor \li \l QMetaType::QString
- \row \li \l QMetaType::QDate \li \l QMetaType::QDateTime,
- \l QMetaType::QString
- \row \li \l QMetaType::QDateTime \li \l QMetaType::QDate,
- \l QMetaType::QString, \l QMetaType::QTime
- \row \li \l QMetaType::Double \li \l QMetaType::Bool, \l QMetaType::Int,
- \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt,
- \l QMetaType::ULongLong
- \row \li \l QMetaType::QFont \li \l QMetaType::QString
- \row \li \l QMetaType::Int \li \l QMetaType::Bool, \l QMetaType::QChar,
- \l QMetaType::Double, \l QMetaType::LongLong, \l QMetaType::QString,
- \l QMetaType::UInt, \l QMetaType::ULongLong
- \row \li \l QMetaType::QKeySequence \li \l QMetaType::Int,
- \l QMetaType::QString
- \row \li \l QMetaType::QVariantList \li \l QMetaType::QStringList (if the
- list's items can be converted to QStrings)
- \row \li \l QMetaType::LongLong \li \l QMetaType::Bool,
- \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::Double,
- \l QMetaType::Int, \l QMetaType::QString, \l QMetaType::UInt,
- \l QMetaType::ULongLong
- \row \li \l QMetaType::QPoint \li QMetaType::QPointF
- \row \li \l QMetaType::QRect \li QMetaType::QRectF
- \row \li \l QMetaType::QString \li \l QMetaType::Bool,
- \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::QColor,
- \l QMetaType::QDate, \l QMetaType::QDateTime, \l QMetaType::Double,
- \l QMetaType::QFont, \l QMetaType::Int, \l QMetaType::QKeySequence,
- \l QMetaType::LongLong, \l QMetaType::QStringList, \l QMetaType::QTime,
- \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid
- \row \li \l QMetaType::QStringList \li \l QMetaType::QVariantList,
- \l QMetaType::QString (if the list contains exactly one item)
- \row \li \l QMetaType::QTime \li \l QMetaType::QString
- \row \li \l QMetaType::UInt \li \l QMetaType::Bool, \l QMetaType::QChar,
- \l QMetaType::Double, \l QMetaType::Int, \l QMetaType::LongLong,
- \l QMetaType::QString, \l QMetaType::ULongLong
- \row \li \l QMetaType::ULongLong \li \l QMetaType::Bool,
- \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int,
- \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt
- \row \li \l QMetaType::QUuid \li \l QMetaType::QByteArray, \l QMetaType::QString
- \endtable
-
- A QVariant containing a pointer to a type derived from QObject will also return true for this
- function if a qobject_cast to the type described by \a targetTypeId would succeed. Note that
- this only works for QObject subclasses which use the Q_OBJECT macro.
-
- A QVariant containing a sequential container will also return true for this
- function if the \a targetTypeId is QVariantList. It is possible to iterate over
- the contents of the container without extracting it as a (copied) QVariantList:
-
- \snippet code/src_corelib_kernel_qvariant.cpp 9
-
- This requires that the value_type of the container is itself a metatype.
-
- Similarly, a QVariant containing a sequential container will also return true for this
- function the \a targetTypeId is QVariantHash or QVariantMap. It is possible to iterate over
- the contents of the container without extracting it as a (copied) QVariantHash or QVariantMap:
-
- \snippet code/src_corelib_kernel_qvariant.cpp 10
-
- \sa convert(), QSequentialIterable, Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(), QAssociativeIterable,
- Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE()
+ \sa QMetaType::canConvert()
*/
-bool QVariant::canConvert(int targetTypeId) const
-{
- if (d.type().id() == targetTypeId)
- return true;
-
-#if QT_CONFIG(itemmodel)
- if ((targetTypeId == QMetaType::QModelIndex
- && d.type().id() == QMetaType::QPersistentModelIndex)
- || (targetTypeId == QMetaType::QPersistentModelIndex
- && d.type().id() == QMetaType::QModelIndex))
- return true;
-#endif
- if (targetTypeId == QMetaType::QVariantList
- && (d.type().id() == QMetaType::QVariantList || d.type().id() == QMetaType::QStringList
- || d.type().id() == QMetaType::QByteArrayList
- || QMetaType::hasRegisteredConverterFunction(
- d.type().id(), qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>()))) {
- return true;
- }
- if ((targetTypeId == QMetaType::QVariantHash || targetTypeId == QMetaType::QVariantMap)
- && (d.type().id() == QMetaType::QVariantMap || d.type().id() == QMetaType::QVariantHash
- || QMetaType::hasRegisteredConverterFunction(
- d.type().id(), qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()))) {
- return true;
- }
-
- if (targetTypeId == qMetaTypeId<QPair<QVariant, QVariant>>()
- && QMetaType::hasRegisteredConverterFunction(
- d.type().id(), qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>())) {
- return true;
- }
+/*!
+ \fn bool QVariant::convert(int targetTypeId)
+ \deprecated [6.0] Use \c convert(QMetaType(targetTypeId)) instead.
- if ((d.type().id() >= QMetaType::User || targetTypeId >= QMetaType::User)
- && QMetaType::hasRegisteredConverterFunction(d.type().id(), targetTypeId)) {
- return true;
- }
+ 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
+ null state similar to that constructed by QVariant(Type).
- // TODO Reimplement this function, currently it works but it is a historical mess.
- uint currentType = d.type().id();
- if (currentType == QMetaType::SChar || currentType == QMetaType::Char)
- currentType = QMetaType::UInt;
- if (targetTypeId == QMetaType::SChar || currentType == QMetaType::Char)
- targetTypeId = QMetaType::UInt;
- if (currentType == QMetaType::Short || currentType == QMetaType::UShort)
- currentType = QMetaType::Int;
- if (targetTypeId == QMetaType::Short || currentType == QMetaType::UShort)
- targetTypeId = QMetaType::Int;
- if (currentType == QMetaType::Float)
- currentType = QMetaType::Double;
- if (targetTypeId == QMetaType::Float)
- targetTypeId = QMetaType::Double;
-
- if (currentType == uint(targetTypeId))
- return true;
+ Returns \c true if the current type of the variant was successfully cast;
+ otherwise returns \c false.
- if (targetTypeId < 0)
- return false;
- if (targetTypeId >= QMetaType::User) {
- if (QMetaType::typeFlags(targetTypeId) & QMetaType::IsEnumeration) {
- targetTypeId = QMetaType::Int;
- } else {
- return canConvertMetaObject(currentType, targetTypeId, d.data.o);
- }
- }
+ A QVariant containing a pointer to a type derived from QObject will also convert
+ and return true for this function if a qobject_cast to the type described
+ by \a targetTypeId would succeed. Note that this only works for QObject subclasses
+ which use the Q_OBJECT macro.
- if (currentType == QMetaType::QJsonValue || targetTypeId == QMetaType::QJsonValue) {
- switch (currentType == QMetaType::QJsonValue ? targetTypeId : currentType) {
- case QMetaType::Nullptr:
- case QMetaType::QString:
- case QMetaType::Bool:
- case QMetaType::Int:
- case QMetaType::UInt:
- case QMetaType::Double:
- case QMetaType::Float:
- case QMetaType::ULong:
- case QMetaType::Long:
- case QMetaType::LongLong:
- case QMetaType::ULongLong:
- case QMetaType::UShort:
- case QMetaType::UChar:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- case QMetaType::QVariantList:
- case QMetaType::QVariantMap:
- case QMetaType::QVariantHash:
- case QMetaType::QCborValue:
- case QMetaType::QCborArray:
- case QMetaType::QCborMap:
- return true;
- default:
- return false;
- }
- }
- if (currentType == QMetaType::QJsonArray)
- return targetTypeId == QMetaType::QVariantList || targetTypeId == QMetaType::QCborValue
- || targetTypeId == QMetaType::QCborArray;
- if (currentType == QMetaType::QJsonObject)
- return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash
- || targetTypeId == QMetaType::QCborValue || targetTypeId == QMetaType::QCborMap;
-
- if (currentType == QMetaType::QCborValue || targetTypeId == QMetaType::QCborValue) {
- switch (currentType == QMetaType::QCborValue ? targetTypeId : currentType) {
- case QMetaType::UnknownType:
- case QMetaType::Nullptr:
- case QMetaType::Bool:
- case QMetaType::Int:
- case QMetaType::UInt:
- case QMetaType::Double:
- case QMetaType::Float:
- case QMetaType::ULong:
- case QMetaType::Long:
- case QMetaType::LongLong:
- case QMetaType::ULongLong:
- case QMetaType::UShort:
- case QMetaType::UChar:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::Short:
- case QMetaType::QString:
- case QMetaType::QByteArray:
- case QMetaType::QDateTime:
- case QMetaType::QUrl:
-#if QT_CONFIG(regularexpression)
- case QMetaType::QRegularExpression:
-#endif
- case QMetaType::QUuid:
- case QMetaType::QVariantList:
- case QMetaType::QVariantMap:
- case QMetaType::QVariantHash:
- case QMetaType::QJsonValue:
- case QMetaType::QJsonArray:
- case QMetaType::QJsonObject:
- case QMetaType::QJsonDocument:
- case QMetaType::QCborArray:
- case QMetaType::QCborMap:
- case QMetaType::QCborSimpleType:
- return true;
- default:
- return false;
- }
- }
- if (currentType == QMetaType::QCborArray)
- return targetTypeId == QMetaType::QVariantList || targetTypeId == QMetaType::QCborValue
- || targetTypeId == QMetaType::QJsonArray;
- if (currentType == QMetaType::QCborMap)
- return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash
- || targetTypeId == QMetaType::QCborValue || targetTypeId == QMetaType::QJsonObject;
-
- // FIXME It should be LastCoreType intead of Uuid
- if (currentType > int(QMetaType::QUuid) || targetTypeId > int(QMetaType::QUuid)) {
- switch (uint(targetTypeId)) {
- case QVariant::Int:
-#if QT_CONFIG(shortcut)
- if (currentType == QVariant::KeySequence)
- return true;
- Q_FALLTHROUGH();
-#endif
- case QVariant::UInt:
- case QVariant::LongLong:
- case QVariant::ULongLong:
- return currentType == QMetaType::ULong
- || currentType == QMetaType::Long
- || currentType == QMetaType::UShort
- || currentType == QMetaType::UChar
- || currentType == QMetaType::Char
- || currentType == QMetaType::SChar
- || currentType == QMetaType::Short
- || QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration;
- case QVariant::Image:
- return currentType == QVariant::Pixmap || currentType == QVariant::Bitmap;
- case QVariant::Pixmap:
- return currentType == QVariant::Image || currentType == QVariant::Bitmap
- || currentType == QVariant::Brush;
- case QVariant::Bitmap:
- return currentType == QVariant::Pixmap || currentType == QVariant::Image;
- case QVariant::ByteArray:
- return currentType == QVariant::Color || currentType == QMetaType::Nullptr
- || ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType));
- case QVariant::String:
- return currentType == QVariant::Font
- || currentType == QVariant::Color || currentType == QMetaType::Nullptr
-#if QT_CONFIG(shortcut)
- || currentType == QVariant::KeySequence
-#endif
- || ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType));
-#if QT_CONFIG(shortcut)
- case QVariant::KeySequence:
- return currentType == QVariant::String || currentType == QVariant::Int;
-#endif
- case QVariant::Font:
- return currentType == QVariant::String;
- case QVariant::Color:
- return currentType == QVariant::String || currentType == QVariant::ByteArray
- || currentType == QVariant::Brush;
- case QVariant::Brush:
- return currentType == QVariant::Color || currentType == QVariant::Pixmap;
- case QMetaType::Long:
- case QMetaType::Char:
- case QMetaType::SChar:
- case QMetaType::UChar:
- case QMetaType::ULong:
- case QMetaType::Short:
- case QMetaType::UShort:
- return currentType == QVariant::Int
- || (currentType < qCanConvertMatrixMaximumTargetType
- && qCanConvertMatrix[QVariant::Int] & (1U << currentType))
- || QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration;
- case QMetaType::QObjectStar:
- return canConvertMetaObject(currentType, targetTypeId, d.data.o);
- default:
- return false;
- }
- }
+ \note converting QVariants that are null due to not being initialized or having
+ failed a previous conversion will always fail, changing the type, remaining null,
+ and returning \c false.
- if (targetTypeId == String && currentType == StringList)
- return v_cast<QStringList>(&d)->count() == 1;
- return currentType < qCanConvertMatrixMaximumTargetType
- && qCanConvertMatrix[targetTypeId] & (1U << currentType);
-}
+ \sa canConvert(), clear()
+*/
/*!
- Casts the variant to the requested type, \a targetTypeId. If the cast cannot be
+ Casts the variant to the requested type, \a targetType. If the cast cannot be
done, the variant is still changed to the requested type, but is left in a cleared
null state similar to that constructed by QVariant(Type).
@@ -3672,122 +2101,115 @@ bool QVariant::canConvert(int targetTypeId) const
A QVariant containing a pointer to a type derived from QObject will also convert
and return true for this function if a qobject_cast to the type described
- by \a targetTypeId would succeed. Note that this only works for QObject subclasses
+ by \a targetType would succeed. Note that this only works for QObject subclasses
which use the Q_OBJECT macro.
\note converting QVariants that are null due to not being initialized or having
failed a previous conversion will always fail, changing the type, remaining null,
and returning \c false.
- \sa canConvert(int targetTypeId), clear()
+ \since 6.0
+
+ \sa canConvert(), clear()
*/
-bool QVariant::convert(int targetTypeId)
+bool QVariant::convert(QMetaType targetType)
{
- if (d.type().id() == targetTypeId)
- return true;
+ if (d.type() == targetType)
+ return targetType.isValid();
QVariant oldValue = *this;
clear();
- if (!oldValue.canConvert(targetTypeId))
+ create(targetType, nullptr);
+ if (!oldValue.canConvert(targetType))
return false;
- create(targetTypeId, nullptr);
// Fail if the value is not initialized or was forced null by a previous failed convert.
if (oldValue.d.is_null && oldValue.d.type().id() != QMetaType::Nullptr)
return false;
- if ((QMetaType::typeFlags(oldValue.userType()) & QMetaType::PointerToQObject) && (QMetaType::typeFlags(targetTypeId) & QMetaType::PointerToQObject)) {
- create(targetTypeId, &oldValue.d.data.o);
- return true;
- }
-
- bool isOk = true;
- int converterType = std::max(oldValue.userType(), targetTypeId);
- if (!handlerManager[converterType]->convert(&oldValue.d, targetTypeId, data(), &isOk))
- isOk = false;
- d.is_null = !isOk;
- return isOk;
+ bool ok = QMetaType::convert(oldValue.d.type(), oldValue.constData(), targetType, data());
+ d.is_null = !ok;
+ return ok;
}
/*!
- \fn bool QVariant::convert(const int type, void *ptr) const
+ \fn bool QVariant::convert(int type, void *ptr) const
\internal
Created for qvariant_cast() usage
*/
-bool QVariant::convert(const int type, void *ptr) const
+bool QVariant::convert(int type, void *ptr) const
{
- return handlerManager[type]->convert(&d, type, ptr, nullptr);
+ return QMetaType::convert(d.type(), constData(), QMetaType(type), ptr);
}
+/*!
+ \internal
+*/
+bool QVariant::view(int type, void *ptr)
+{
+ return QMetaType::view(d.type(), data(), QMetaType(type), ptr);
+}
/*!
- \fn bool operator==(const QVariant &v1, const QVariant &v2)
+ \fn bool QVariant::operator==(const QVariant &lhs, const QVariant &rhs)
- \relates QVariant
+ Returns \c true if \a lhs and \a rhs are equal; otherwise returns \c false.
- Returns \c true if \a v1 and \a v2 are equal; otherwise returns \c false.
+ QVariant uses the equality operator of the type() contained to check for
+ equality.
- If \a v1 and \a v2 have the same \l{QVariant::}{type()}, the
- type's equality operator is used for comparison. If not, it is
- attempted to \l{QVariant::}{convert()} \a v2 to the same type as
- \a v1. See \l{QVariant::}{canConvert()} for a list of possible
- conversions.
+ Variants of different types will always compare as not equal with a few
+ exceptions:
+
+ \list
+ \li If both types are numeric types (integers and floatins point numbers)
+ Qt will compare those types using standard C++ type promotion rules.
+ \li If one type is numeric and the other one a QString, Qt will try to
+ convert the QString to a matching numeric type and if successful compare
+ those.
+ \li If both variants contain pointers to QObject derived types, QVariant
+ will check whether the types are related and point to the same object.
+ \endlist
The result of the function is not affected by the result of QVariant::isNull,
which means that two values can be equal even if one of them is null and
another is not.
-
- \warning To make this function work with a custom type registered with
- qRegisterMetaType(), its comparison operator must be registered using
- QMetaType::registerComparators().
*/
-/*!
- \fn bool operator!=(const QVariant &v1, const QVariant &v2)
-
- \relates QVariant
-
- Returns \c false if \a v1 and \a v2 are equal; otherwise returns \c true.
-
- \warning To make this function work with a custom type registered with
- qRegisterMetaType(), its comparison operator must be registered using
- QMetaType::registerComparators().
-*/
-
-/*! \fn bool QVariant::operator==(const QVariant &v) const
- Compares this QVariant with \a v and returns \c true if they are
- equal; otherwise returns \c false.
-
- QVariant uses the equality operator of the type() it contains to
- check for equality. QVariant will try to convert() \a v if its
- type is not the same as this variant's type. See canConvert() for
- a list of possible conversions.
+/*!
+ \fn bool QVariant::operator!=(const QVariant &lhs, const QVariant &rhs)
- \warning To make this function work with a custom type registered with
- qRegisterMetaType(), its comparison operator must be registered using
- QMetaType::registerComparators().
-*/
+ Returns \c false if \a lhs and \a rhs are equal; otherwise returns \c true.
-/*!
- \fn bool QVariant::operator!=(const QVariant &v) const
+ QVariant uses the equality operator of the type() contained to check for
+ equality.
- Compares this QVariant with \a v and returns \c true if they are not
- equal; otherwise returns \c false.
+ Variants of different types will always compare as not equal with a few
+ exceptions:
- \warning To make this function work with a custom type registered with
- qRegisterMetaType(), its comparison operator must be registered using
- QMetaType::registerComparators().
+ \list
+ \li If both types are numeric types (integers and floatins point numbers)
+ Qt will compare those types using standard C++ type promotion rules.
+ \li If one type is numeric and the other one a QString, Qt will try to
+ convert the QString to a matching numeric type and if successful compare
+ those.
+ \li If both variants contain pointers to QObject derived types, QVariant
+ will check whether the types are related and point to the same object.
+ \endlist
*/
static bool qIsNumericType(uint tp)
{
static const qulonglong numericTypeBits =
+ Q_UINT64_C(1) << QMetaType::QString |
Q_UINT64_C(1) << QMetaType::Bool |
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 |
@@ -3803,33 +2225,56 @@ 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))
+ return QMetaType::Bool;
// C++ integral ranks: (4.13 Integer conversion rank [conv.rank])
// bool < signed char < short < int < long < long long
@@ -3849,175 +2294,260 @@ 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 (t1 == QMetaType::LongLong || t2 == QMetaType::LongLong)
+ if (isUnsigned2 && iface2->size > sizeof(int))
+ return QMetaType::ULongLong;
+
+ // 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 int integralCompare(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);
- Q_ASSERT(ok);
+ 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;
+ }
- qlonglong l2 = qConvertToNumber(d2, &ok);
- Q_ASSERT(ok);
+ 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;
+ return smaller ? QPartialOrdering::Less : QPartialOrdering::Greater;
+}
- if (promotedType == QMetaType::Int)
- return int(l1) < int(l2) ? -1 : int(l1) == int(l2) ? 0 : 1;
+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
+ 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 uint(l1) < uint(l2) ? -1 : uint(l1) == uint(l2) ? 0 : 1;
+ return spaceShip<uint>(*l1, *l2);
if (promotedType == QMetaType::LongLong)
- return l1 < l2 ? -1 : l1 == l2 ? 0 : 1;
+ return spaceShip<qlonglong>(*l1, *l2);
if (promotedType == QMetaType::ULongLong)
- return qulonglong(l1) < qulonglong(l2) ? -1 : qulonglong(l1) == qulonglong(l2) ? 0 : 1;
+ return spaceShip<qulonglong>(*l1, *l2);
- Q_UNREACHABLE();
- return 0;
+ return spaceShip<int>(*l1, *l2);
}
-static 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->type().id(), d2->type().id());
+ 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);
- Q_ASSERT(ok);
- qreal r2 = qConvertToRealNumber(d2, &ok);
- Q_ASSERT(ok);
- if (r1 == r2)
- return 0;
-
- // only do fuzzy comparisons for finite, non-zero numbers
- int c1 = qFpClassify(r1);
- int c2 = qFpClassify(r2);
- if ((c1 == FP_NORMAL || c1 == FP_SUBNORMAL) && (c2 == FP_NORMAL || c2 == FP_SUBNORMAL)) {
- if (qFuzzyCompare(r1, r2))
- return 0;
+ // 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 spaceShip(*r1, *r2);
+}
+
+#ifndef QT_BOOTSTRAPPED
+static bool qvCanConvertMetaObject(QMetaType fromType, QMetaType toType)
+{
+ 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;
+}
- return r1 < r2 ? -1 : 1;
+static QPartialOrdering pointerCompare(const QVariant::Private *d1, const QVariant::Private *d2)
+{
+ return spaceShip<QObject *>(d1->get<QObject *>(), d2->get<QObject *>());
}
+#endif
/*!
\internal
*/
-bool QVariant::cmp(const QVariant &v) const
+bool QVariant::equals(const QVariant &v) const
{
- auto cmp_helper = [](const QVariant::Private &d1, const QVariant::Private &d2) {
- Q_ASSERT(d1.type() == d2.type());
- if (d1.type().id() >= QMetaType::User) {
- int result;
- if (QMetaType::equals(QT_PREPEND_NAMESPACE(constData(d1)),
- QT_PREPEND_NAMESPACE(constData(d2)), d1.type().id(), &result))
- return result == 0;
- }
- return handlerManager[d1.type().id()]->compare(&d1, &d2);
- };
+ auto metatype = d.type();
- // try numerics first, with C++ type promotion rules (no conversion)
- if (qIsNumericType(d.type().id()) && qIsNumericType(v.d.type().id()))
- return numericCompare(&d, &v.d) == 0;
+ if (metatype != v.metaType()) {
+ // try numeric comparisons, with C++ type promotion rules (no conversion)
+ 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 (qvCanConvertMetaObject(metatype, v.metaType()))
+ return pointerCompare(&d, &v.d) == QPartialOrdering::Equivalent;
+#endif
+ return false;
+ }
- if (d.type() == v.d.type())
- return cmp_helper(d, v.d);
+ // For historical reasons: QVariant() == QVariant()
+ if (!metatype.isValid())
+ return true;
- QVariant v1 = *this;
- QVariant v2 = v;
- if (v2.canConvert(v1.d.type().id())) {
- if (!v2.convert(v1.d.type().id()))
- return false;
- } else {
- // try the opposite conversion, it might work
- qSwap(v1, v2);
- if (!v2.convert(v1.d.type().id()))
- return false;
- }
- return cmp_helper(v1.d, v2.d);
+ return metatype.equals(d.storage(), v.d.storage());
}
/*!
- \internal
- */
+ Compares the objects at \a lhs and \a rhs for ordering.
-const void *QVariant::constData() const
+ Returns QPartialOrdering::Unordered if comparison is not supported
+ or the values are unordered. Otherwise, returns
+ QPartialOrdering::Less, QPartialOrdering::Equivalent or
+ QPartialOrdering::Greater if \a lhs is less than, equivalent
+ to or greater than \a rhs, respectively.
+
+ If the variants contain data with a different metatype, the values are considered
+ unordered unless they are both of numeric or pointer types, where regular numeric or
+ pointer comparison rules will be used.
+ \note: If a numeric comparison is done and at least one value is NaN, QPartialOrdering::Unordered
+ is returned.
+
+ If both variants contain data of the same metatype, the method will use the
+ QMetaType::compare method to determine the ordering of the two variants, which can
+ also indicate that it can't establish an ordering between the two values.
+
+ \since 6.0
+ \sa QMetaType::compare(), QMetaType::isOrdered()
+*/
+QPartialOrdering QVariant::compare(const QVariant &lhs, const QVariant &rhs)
{
- return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data);
+ QMetaType t = lhs.d.type();
+ if (t != rhs.d.type()) {
+ // try numeric comparisons, with C++ type promotion rules (no conversion)
+ if (canBeNumericallyCompared(lhs.d.type().iface(), rhs.d.type().iface()))
+ return numericCompare(&lhs.d, &rhs.d);
+#ifndef QT_BOOTSTRAPPED
+ if (qvCanConvertMetaObject(lhs.metaType(), rhs.metaType()))
+ return pointerCompare(&lhs.d, &rhs.d);
+#endif
+ return QPartialOrdering::Unordered;
+ }
+ return t.compare(lhs.constData(), rhs.constData());
}
/*!
+ \fn const void *QVariant::constData() const
\fn const void* QVariant::data() const
- \internal
-*/
+ Returns a pointer to the contained object as a generic void* that cannot be
+ written to.
+
+ \sa get_if(), QMetaType
+ */
/*!
- \internal
+ Returns a pointer to the contained object as a generic void* that can be
+ written to.
+
+ This function detaches the QVariant. When called on a \l{isNull}{null-QVariant},
+ the QVariant will not be null after the call.
+
+ \sa get_if(), QMetaType
*/
-void* QVariant::data()
+void *QVariant::data()
{
detach();
+ // set is_null to false, as the caller is likely to write some data into this variant
+ d.is_null = false;
return const_cast<void *>(constData());
}
+/*!
+ \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()
+*/
/*!
- Returns \c true if this is a null variant, false otherwise. A variant is
- considered null if it contains no initialized value, or the contained value
- is \nullptr or is an instance of a built-in type that has an isNull
- method, in which case the result would be the same as calling isNull on the
- wrapped object.
+ \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)
- \warning Null variants is not a single state and two null variants may easily
- return \c false on the == operator if they do not contain similar null values.
+ If \a v contains an object of type \c T, returns a reference to the contained
+ object, otherwise the call has undefined behavior.
- \sa convert(int)
+ 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.
+
+ \note This behavior has been changed from Qt 5, where isNull() would also
+ return true if the variant contained an object of a builtin type with an isNull()
+ method that returned true for that object.
+
+ \sa convert()
*/
bool QVariant::isNull() const
{
- return handlerManager[d.type().id()]->isNull(&d);
+ if (d.is_null || !metaType().isValid())
+ return true;
+ if (metaType().flags() & QMetaType::IsPointer)
+ return d.get<void *>() == nullptr;
+ return false;
}
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QVariant &v)
+QDebug QVariant::qdebugHelper(QDebug dbg) const
{
QDebugStateSaver saver(dbg);
- const uint typeId = v.d.type().id();
+ const uint typeId = d.type().id();
dbg.nospace() << "QVariant(";
if (typeId != QMetaType::UnknownType) {
- dbg << QMetaType::typeName(typeId) << ", ";
- bool userStream = false;
- bool canConvertToString = false;
- if (typeId >= QMetaType::User) {
- userStream = QMetaType::debugStream(dbg, constData(v.d), typeId);
- canConvertToString = v.canConvert<QString>();
- }
- if (!userStream && canConvertToString)
- dbg << v.toString();
- else if (!userStream)
- handlerManager[typeId]->debugStream(dbg, v);
+ dbg << d.type().name() << ", ";
+ bool streamed = d.type().debugStream(dbg, d.storage());
+ if (!streamed && canConvert<QString>())
+ dbg << toString();
} else {
dbg << "Invalid";
}
@@ -4025,19 +2555,42 @@ QDebug operator<<(QDebug dbg, const QVariant &v)
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
+
QDebug operator<<(QDebug dbg, const QVariant::Type p)
{
QDebugStateSaver saver(dbg);
dbg.nospace() << "QVariant::"
<< (int(p) != int(QMetaType::UnknownType)
- ? QMetaType::typeName(p)
+ ? QMetaType(p).name()
: "Invalid");
return dbg;
}
+
+QT_WARNING_POP
#endif
+#endif
-/*! \fn template<typename T> void QVariant::setValue(const 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
@@ -4050,7 +2603,19 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\sa value(), fromValue(), canConvert()
*/
-/*! \fn template<typename T> T QVariant::value() const
+/*! \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 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 &
Returns the stored value converted to the template type \c{T}.
Call canConvert() to find out whether a type can be converted.
@@ -4078,7 +2643,19 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\sa setValue(), fromValue(), canConvert(), Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE()
*/
-/*! \fn bool QVariant::canConvert() const
+/*! \fn template<typename T> T QVariant::view()
+
+ Returns a mutable view of template type \c{T} on the stored value.
+ Call canView() to find out whether such a view is supported.
+ If no such view can be created, returns the stored value converted to the
+ template type \c{T}. Call canConvert() to find out whether a type can be
+ converted. If the value can neither be viewed nor converted, a
+ \l{default-constructed value} will be returned.
+
+ \sa canView(), Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE()
+*/
+
+/*! \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.
@@ -4094,6 +2671,14 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\sa convert()
*/
+/*! \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.
+
+ \sa value()
+*/
+
/*! \fn template<typename T> static QVariant QVariant::fromValue(const T &value)
Returns a QVariant containing a copy of \a value. Behaves
@@ -4103,12 +2688,15 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\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
@@ -4122,45 +2710,46 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\sa fromValue()
*/
-#if QT_DEPRECATED_SINCE(5, 14)
/*!
- \fn template<typename T> QVariant qVariantFromValue(const T &value)
- \relates QVariant
- \obsolete
-
- Returns a variant containing a copy of the given \a value
- with template type \c{T}.
-
- This function is equivalent to QVariant::fromValue(\a value).
-
- \note This function was provided as a workaround for MSVC 6
- which did not support member template functions. It is advised
- to use the other form in new code.
+ \fn template<typename... Types> QVariant QVariant::fromStdVariant(std::variant<Types...> &&value)
+ \since 6.6
+ \overload
+*/
- For example, a QObject pointer can be stored in a variant with the
- following code:
- \snippet code/src_corelib_kernel_qvariant.cpp 8
+/*!
+ \since 6.7
- \sa QVariant::fromValue()
-*/
+ 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).
-/*! \fn template<typename T> void qVariantSetValue(QVariant &variant, const T &value)
- \relates QVariant
- \obsolete
+ Note that you have to pass the address of the object you want stored.
- Sets the contents of the given \a variant to a copy of the
- \a value with the specified template type \c{T}.
+ 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.
- This function is equivalent to QVariant::setValue(\a value).
+ 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.
- \note This function was provided as a workaround for MSVC 6
- which did not support member template functions. It is advised
- to use the other form in new code.
+ Returns the QVariant created as described above.
- \sa QVariant::setValue()
+ \sa QVariant::fromValue(), QMetaType::Type
*/
-#endif
+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)
@@ -4173,9 +2762,17 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\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
- \obsolete
+ \deprecated
Returns the given \a value converted to the template type \c{T}.
@@ -4191,7 +2788,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
/*! \fn bool qVariantCanConvert(const QVariant &value)
\relates QVariant
- \obsolete
+ \deprecated
Returns \c true if the given \a value can be converted to the
template type specified; otherwise returns \c false.
@@ -4278,655 +2875,157 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
*/
/*!
- \class QSequentialIterable
- \since 5.2
- \inmodule QtCore
- \brief The QSequentialIterable class is an iterable interface for a container in a QVariant.
-
- This class allows several methods of accessing the elements of a container held within
- a QVariant. An instance of QSequentialIterable can be extracted from a QVariant if it can
- be converted to a QVariantList.
-
- \snippet code/src_corelib_kernel_qvariant.cpp 9
-
- The container itself is not copied before iterating over it.
-
- \sa QVariant
-*/
-
-/*!
\internal
-*/
-QSequentialIterable::QSequentialIterable(const QtMetaTypePrivate::QSequentialIterableImpl &impl)
- : m_impl(impl)
-{
-}
-
-QSequentialIterable::const_iterator::const_iterator(const QSequentialIterable &iter, QAtomicInt *ref_)
- : m_impl(iter.m_impl), ref(ref_)
-{
- ref->ref();
-}
-
-QSequentialIterable::const_iterator::const_iterator(const QtMetaTypePrivate::QSequentialIterableImpl &impl, QAtomicInt *ref_)
- : m_impl(impl), ref(ref_)
-{
- ref->ref();
-}
-
-void QSequentialIterable::const_iterator::begin()
-{
- m_impl.moveToBegin();
-}
-
-void QSequentialIterable::const_iterator::end()
-{
- m_impl.moveToEnd();
-}
-
-/*! \fn QSequentialIterable::const_iterator QSequentialIterable::begin() const
-
- Returns a QSequentialIterable::const_iterator for the beginning of the container. This
- can be used in stl-style iteration.
-
- \sa end()
-*/
-QSequentialIterable::const_iterator QSequentialIterable::begin() const
-{
- const_iterator it(*this, new QAtomicInt(0));
- it.begin();
- return it;
-}
-
-/*!
- Returns a QSequentialIterable::const_iterator for the end of the container. This
- can be used in stl-style iteration.
-
- \sa begin()
-*/
-QSequentialIterable::const_iterator QSequentialIterable::end() const
-{
- const_iterator it(*this, new QAtomicInt(0));
- it.end();
- return it;
-}
-
-static const QVariant variantFromVariantDataHelper(const QtMetaTypePrivate::VariantData &d) {
- QVariant v;
- if (d.metaTypeId == qMetaTypeId<QVariant>())
- v = *reinterpret_cast<const QVariant*>(d.data);
- else
- v = QVariant(d.metaTypeId, d.data, d.flags & ~QVariantConstructionFlags::ShouldDeleteVariantData);
- if (d.flags & QVariantConstructionFlags::ShouldDeleteVariantData)
- QMetaType::destroy(d.metaTypeId, const_cast<void *>(d.data));
- return v;
-}
-
-/*!
- Returns the element at position \a idx in the container.
-*/
-QVariant QSequentialIterable::at(int idx) const
-{
- const QtMetaTypePrivate::VariantData d = m_impl.at(idx);
- return variantFromVariantDataHelper(d);
-}
-
-/*!
- Returns the number of elements in the container.
-*/
-int QSequentialIterable::size() const
+ */
+const void *QtPrivate::QVariantTypeCoercer::convert(const QVariant &value, const QMetaType &type)
{
- return m_impl.size();
-}
+ if (type == QMetaType::fromType<QVariant>())
+ return &value;
-/*!
- Returns whether it is possible to iterate over the container in reverse. This
- corresponds to the std::bidirectional_iterator_tag iterator trait of the
- const_iterator of the container.
-*/
-bool QSequentialIterable::canReverseIterate() const
-{
- return m_impl._iteratorCapabilities & QtMetaTypePrivate::BiDirectionalCapability;
-}
+ if (type == value.metaType())
+ return value.constData();
-/*!
- \class QSequentialIterable::const_iterator
- \since 5.2
- \inmodule QtCore
- \brief The QSequentialIterable::const_iterator allows iteration over a container in a QVariant.
-
- A QSequentialIterable::const_iterator can only be created by a QSequentialIterable instance,
- and can be used in a way similar to other stl-style iterators.
-
- \snippet code/src_corelib_kernel_qvariant.cpp 9
-
- \sa QSequentialIterable
-*/
-
-
-/*!
- Destroys the QSequentialIterable::const_iterator.
-*/
-QSequentialIterable::const_iterator::~const_iterator() {
- if (!ref->deref()) {
- m_impl.destroyIter();
- delete ref;
+ if (value.canConvert(type)) {
+ converted = value;
+ if (converted.convert(type))
+ return converted.constData();
}
-}
-/*!
- Creates a copy of \a other.
-*/
-QSequentialIterable::const_iterator::const_iterator(const const_iterator &other)
- : m_impl(other.m_impl), ref(other.ref)
-{
- ref->ref();
+ return nullptr;
}
/*!
- Assigns \a other to this.
-*/
-QSequentialIterable::const_iterator&
-QSequentialIterable::const_iterator::operator=(const const_iterator &other)
-{
- other.ref->ref();
- if (!ref->deref()) {
- m_impl.destroyIter();
- delete ref;
- }
- m_impl = other.m_impl;
- ref = other.ref;
- return *this;
-}
-
-/*!
- Returns the current item, converted to a QVariant.
-*/
-const QVariant QSequentialIterable::const_iterator::operator*() const
-{
- const QtMetaTypePrivate::VariantData d = m_impl.getCurrent();
- return variantFromVariantDataHelper(d);
-}
-
-/*!
- Returns \c true if \a other points to the same item as this
- iterator; otherwise returns \c false.
-
- \sa operator!=()
-*/
-bool QSequentialIterable::const_iterator::operator==(const const_iterator &other) const
-{
- return m_impl.equal(other.m_impl);
-}
-
-/*!
- Returns \c true if \a other points to a different item than this
- iterator; otherwise returns \c false.
-
- \sa operator==()
-*/
-bool QSequentialIterable::const_iterator::operator!=(const const_iterator &other) const
+ \internal
+ */
+const void *QtPrivate::QVariantTypeCoercer::coerce(const QVariant &value, const QMetaType &type)
{
- return !m_impl.equal(other.m_impl);
-}
-
-/*!
- The prefix ++ operator (\c{++it}) advances the iterator to the
- next item in the container and returns an iterator to the new current
- item.
+ if (const void *result = convert(value, type))
+ return result;
- Calling this function on QSequentialIterable::end() leads to undefined results.
-
- \sa operator--()
-*/
-QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator++()
-{
- m_impl.advance(1);
- return *this;
+ converted = QVariant(type);
+ return converted.constData();
}
/*!
- \overload
+ \class QVariantRef
+ \since 6.0
+ \inmodule QtCore
+ \brief The QVariantRef acts as a non-const reference to a QVariant.
- The postfix ++ operator (\c{it++}) advances the iterator to the
- next item in the container and returns an iterator to the previously
- current item.
+ As the generic iterators don't actually instantiate a QVariant on each
+ step, they cannot return a reference to one from operator*(). QVariantRef
+ provides the same functionality as an actual reference to a QVariant would,
+ but is backed by a pointer given as template parameter. The template is
+ implemented for pointers of type QSequentialIterator and
+ QAssociativeIterator.
*/
-QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator++(int)
-{
- QtMetaTypePrivate::QSequentialIterableImpl impl;
- impl.copy(m_impl);
- m_impl.advance(1);
- return const_iterator(impl, new QAtomicInt(0));
-}
/*!
- The prefix -- operator (\c{--it}) makes the preceding item
- current and returns an iterator to the new current item.
+ \fn template<typename Pointer> QVariantRef<Pointer>::QVariantRef(const Pointer *pointer)
- Calling this function on QSequentialIterable::begin() leads to undefined results.
-
- If the container in the QVariant does not support bi-directional iteration, calling this function
- leads to undefined results.
-
- \sa operator++(), canReverseIterate()
-*/
-QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator--()
-{
- m_impl.advance(-1);
- return *this;
-}
+ Creates a QVariantRef from an \a pointer.
+ */
/*!
- \overload
-
- The postfix -- operator (\c{it--}) makes the preceding item
- current and returns an iterator to the previously current item.
+ \fn template<typename Pointer> QVariantRef<Pointer> &QVariantRef<Pointer>::operator=(const QVariant &value)
- If the container in the QVariant does not support bi-directional iteration, calling this function
- leads to undefined results.
-
- \sa canReverseIterate()
-*/
-QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator--(int)
-{
- QtMetaTypePrivate::QSequentialIterableImpl impl;
- impl.copy(m_impl);
- m_impl.advance(-1);
- return const_iterator(impl, new QAtomicInt(0));
-}
+ Assigns a new \a value to the value pointed to by the pointer this
+ QVariantRef refers to.
+ */
/*!
- Advances the iterator by \a j items.
+ \fn template<typename Pointer> QVariantRef<Pointer> &QVariantRef<Pointer>::operator=(const QVariantRef &value)
- \sa operator-=(), operator+()
-*/
-QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator+=(int j)
-{
- m_impl.advance(j);
- return *this;
-}
+ Assigns a new \a value to the value pointed to by the pointer this
+ QVariantRef refers to.
+ */
/*!
- Makes the iterator go back by \a j items.
-
- If the container in the QVariant does not support bi-directional iteration, calling this function
- leads to undefined results.
+ \fn template<typename Pointer> QVariantRef<Pointer> &QVariantRef<Pointer>::operator=(QVariantRef &&value)
- \sa operator+=(), operator-(), canReverseIterate()
+ Assigns a new \a value to the value pointed to by the pointer this
+ QVariantRef refers to.
*/
-QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator-=(int j)
-{
- m_impl.advance(-j);
- return *this;
-}
/*!
- Returns an iterator to the item at \a j positions forward from
- this iterator.
+ \fn template<typename Pointer> QVariantRef<Pointer>::operator QVariant() const
- \sa operator-(), operator+=()
+ Resolves the QVariantRef to an actual QVariant.
*/
-QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator+(int j) const
-{
- QtMetaTypePrivate::QSequentialIterableImpl impl;
- impl.copy(m_impl);
- impl.advance(j);
- return const_iterator(impl, new QAtomicInt(0));
-}
/*!
- Returns an iterator to the item at \a j positions backward from
- this iterator.
+ \fn template<typename Pointer> void swap(QVariantRef<Pointer> a, QVariantRef<Pointer> b)
- If the container in the QVariant does not support bi-directional iteration, calling this function
- leads to undefined results.
-
- \sa operator+(), operator-=(), canReverseIterate()
+ Swaps the values pointed to by the pointers the QVariantRefs
+ \a a and \a b refer to.
*/
-QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator-(int j) const
-{
- QtMetaTypePrivate::QSequentialIterableImpl impl;
- impl.copy(m_impl);
- impl.advance(-j);
- return const_iterator(impl, new QAtomicInt(0));
-}
/*!
- \class QAssociativeIterable
- \since 5.2
+ \class QVariantConstPointer
+ \since 6.0
\inmodule QtCore
- \brief The QAssociativeIterable class is an iterable interface for an associative container in a QVariant.
-
- This class allows several methods of accessing the elements of an associative container held within
- a QVariant. An instance of QAssociativeIterable can be extracted from a QVariant if it can
- be converted to a QVariantHash or QVariantMap.
-
- \snippet code/src_corelib_kernel_qvariant.cpp 10
-
- The container itself is not copied before iterating over it.
-
- \sa QVariant
-*/
-
-/*!
- \internal
-*/
-QAssociativeIterable::QAssociativeIterable(const QtMetaTypePrivate::QAssociativeIterableImpl &impl)
- : m_impl(impl)
-{
-}
-
-QAssociativeIterable::const_iterator::const_iterator(const QAssociativeIterable &iter, QAtomicInt *ref_)
- : m_impl(iter.m_impl), ref(ref_)
-{
- ref->ref();
-}
-
-QAssociativeIterable::const_iterator::const_iterator(const QtMetaTypePrivate::QAssociativeIterableImpl &impl, QAtomicInt *ref_)
- : m_impl(impl), ref(ref_)
-{
- ref->ref();
-}
-
-void QAssociativeIterable::const_iterator::begin()
-{
- m_impl.begin();
-}
-
-void QAssociativeIterable::const_iterator::end()
-{
- m_impl.end();
-}
-
-void QAssociativeIterable::const_iterator::find(const QVariant &key)
-{
- Q_ASSERT(key.userType() == m_impl._metaType_id_key);
- const QtMetaTypePrivate::VariantData dkey(key.userType(), key.constData(), 0 /*key.flags()*/);
- m_impl.find(dkey);
-}
-
-/*!
- Returns a QAssociativeIterable::const_iterator for the beginning of the container. This
- can be used in stl-style iteration.
+ \brief Emulated const pointer to QVariant based on a pointer.
- \sa end()
+ QVariantConstPointer wraps a QVariant and returns it from its operator*().
+ This makes it suitable as replacement for an actual const pointer. We cannot
+ return an actual const pointer from generic iterators as the iterators don't
+ hold an actual QVariant.
*/
-QAssociativeIterable::const_iterator QAssociativeIterable::begin() const
-{
- const_iterator it(*this, new QAtomicInt(0));
- it.begin();
- return it;
-}
/*!
- Returns a QAssociativeIterable::const_iterator for the end of the container. This
- can be used in stl-style iteration.
-
- \sa begin()
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::end() const
-{
- const_iterator it(*this, new QAtomicInt(0));
- it.end();
- return it;
-}
-
-/*!
- \since 5.5
-
- Returns a QAssociativeIterable::const_iterator for the given key \a key
- in the container, if the types are convertible.
-
- If the key is not found, returns end().
-
- This can be used in stl-style iteration.
-
- \sa begin(), end(), value()
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::find(const QVariant &key) const
+ Constructs a QVariantConstPointer from a \a variant.
+ */
+QVariantConstPointer::QVariantConstPointer(QVariant variant)
+ : m_variant(std::move(variant))
{
- const_iterator it(*this, new QAtomicInt(0));
- QVariant key_ = key;
- if (key_.canConvert(m_impl._metaType_id_key) && key_.convert(m_impl._metaType_id_key))
- it.find(key_);
- else
- it.end();
- return it;
}
/*!
- Returns the value for the given \a key in the container, if the types are convertible.
-
- \sa find()
-*/
-QVariant QAssociativeIterable::value(const QVariant &key) const
+ Dereferences the QVariantConstPointer to retrieve its internal QVariant.
+ */
+QVariant QVariantConstPointer::operator*() const
{
- const const_iterator it = find(key);
- if (it == end())
- return QVariant();
- return *it;
+ return m_variant;
}
/*!
- Returns the number of elements in the container.
-*/
-int QAssociativeIterable::size() const
+ Returns a const pointer to the QVariant, conforming to the
+ conventions for operator->().
+ */
+const QVariant *QVariantConstPointer::operator->() const
{
- return m_impl.size();
+ return &m_variant;
}
/*!
- \class QAssociativeIterable::const_iterator
- \since 5.2
+ \class QVariantPointer
+ \since 6.0
\inmodule QtCore
- \brief The QAssociativeIterable::const_iterator allows iteration over a container in a QVariant.
-
- A QAssociativeIterable::const_iterator can only be created by a QAssociativeIterable instance,
- and can be used in a way similar to other stl-style iterators.
-
- \snippet code/src_corelib_kernel_qvariant.cpp 10
-
- \sa QAssociativeIterable
-*/
-
+ \brief QVariantPointer is a template class that emulates a pointer to QVariant based on a pointer.
-/*!
- Destroys the QAssociativeIterable::const_iterator.
+ QVariantConstPointer wraps a pointer and returns QVariantRef to it from its
+ operator*(). This makes it suitable as replacement for an actual pointer. We
+ cannot return an actual pointer from generic iterators as the iterators don't
+ hold an actual QVariant.
*/
-QAssociativeIterable::const_iterator::~const_iterator()
-{
- if (!ref->deref()) {
- m_impl.destroyIter();
- delete ref;
- }
-}
/*!
- Creates a copy of \a other.
-*/
-QAssociativeIterable::const_iterator::const_iterator(const const_iterator &other)
- : m_impl(other.m_impl), ref(other.ref)
-{
- ref->ref();
-}
+ \fn template<typename Pointer> QVariantPointer<Pointer>::QVariantPointer(const Pointer *pointer)
-/*!
- Assigns \a other to this.
-*/
-QAssociativeIterable::const_iterator&
-QAssociativeIterable::const_iterator::operator=(const const_iterator &other)
-{
- other.ref->ref();
- if (!ref->deref()) {
- m_impl.destroyIter();
- delete ref;
- }
- m_impl = other.m_impl;
- ref = other.ref;
- return *this;
-}
-
-/*!
- Returns the current value, converted to a QVariant.
-*/
-const QVariant QAssociativeIterable::const_iterator::operator*() const
-{
- const QtMetaTypePrivate::VariantData d = m_impl.getCurrentValue();
- return variantFromVariantDataHelper(d);
-}
-
-/*!
- Returns the current key, converted to a QVariant.
-*/
-const QVariant QAssociativeIterable::const_iterator::key() const
-{
- const QtMetaTypePrivate::VariantData d = m_impl.getCurrentKey();
- return variantFromVariantDataHelper(d);
-}
-
-/*!
- Returns the current value, converted to a QVariant.
-*/
-const QVariant QAssociativeIterable::const_iterator::value() const
-{
- return operator*();
-}
-
-/*!
- Returns \c true if \a other points to the same item as this
- iterator; otherwise returns \c false.
-
- \sa operator!=()
-*/
-bool QAssociativeIterable::const_iterator::operator==(const const_iterator &other) const
-{
- return m_impl.equal(other.m_impl);
-}
-
-/*!
- Returns \c true if \a other points to a different item than this
- iterator; otherwise returns \c false.
-
- \sa operator==()
-*/
-bool QAssociativeIterable::const_iterator::operator!=(const const_iterator &other) const
-{
- return !m_impl.equal(other.m_impl);
-}
-
-/*!
- The prefix ++ operator (\c{++it}) advances the iterator to the
- next item in the container and returns an iterator to the new current
- item.
-
- Calling this function on QAssociativeIterable::end() leads to undefined results.
-
- \sa operator--()
-*/
-QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator++()
-{
- m_impl.advance(1);
- return *this;
-}
-
-/*!
- \overload
-
- The postfix ++ operator (\c{it++}) advances the iterator to the
- next item in the container and returns an iterator to the previously
- current item.
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator++(int)
-{
- QtMetaTypePrivate::QAssociativeIterableImpl impl;
- impl.copy(m_impl);
- m_impl.advance(1);
- return const_iterator(impl, new QAtomicInt(0));
-}
-
-/*!
- The prefix -- operator (\c{--it}) makes the preceding item
- current and returns an iterator to the new current item.
-
- Calling this function on QAssociativeIterable::begin() leads to undefined results.
-
- \sa operator++()
-*/
-QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator--()
-{
- m_impl.advance(-1);
- return *this;
-}
-
-/*!
- \overload
-
- The postfix -- operator (\c{it--}) makes the preceding item
- current and returns an iterator to the previously current item.
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator--(int)
-{
- QtMetaTypePrivate::QAssociativeIterableImpl impl;
- impl.copy(m_impl);
- m_impl.advance(-1);
- return const_iterator(impl, new QAtomicInt(0));
-}
-
-/*!
- Advances the iterator by \a j items.
-
- \sa operator-=(), operator+()
-*/
-QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator+=(int j)
-{
- m_impl.advance(j);
- return *this;
-}
-
-/*!
- Makes the iterator go back by \a j items.
-
- \sa operator+=(), operator-()
-*/
-QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator-=(int j)
-{
- m_impl.advance(-j);
- return *this;
-}
+ Constructs a QVariantPointer from the given \a pointer.
+ */
/*!
- Returns an iterator to the item at \a j positions forward from
- this iterator.
+ \fn template<typename Pointer> QVariantRef<Pointer> QVariantPointer<Pointer>::operator*() const
- \sa operator-(), operator+=()
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator+(int j) const
-{
- QtMetaTypePrivate::QAssociativeIterableImpl impl;
- impl.copy(m_impl);
- impl.advance(j);
- return const_iterator(impl, new QAtomicInt(0));
-}
+ Dereferences the QVariantPointer to a QVariantRef.
+ */
/*!
- Returns an iterator to the item at \a j positions backward from
- this iterator.
-
- \sa operator+(), operator-=()
-*/
-QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator-(int j) const
-{
- QtMetaTypePrivate::QAssociativeIterableImpl impl;
- impl.copy(m_impl);
- impl.advance(-j);
- return const_iterator(impl, new QAtomicInt(0));
-}
+ \fn template<typename Pointer> Pointer QVariantPointer<Pointer>::operator->() const
-QVariant::Private::~Private()
-{
- QtMetaTypePrivate::derefAndDestroy(
- reinterpret_cast<QtPrivate::QMetaTypeInterface *>(packedType << 2));
-}
+ Dereferences and returns the pointer. The pointer is expected to also
+ implement operator->().
+ */
QT_END_NAMESPACE