QVariant: add fromMetaType
The QVariant(QMetaType) constructor is a major anti-pattern: unlike *every* other QVariant's constructor, it doesn't build a QVariant holding the QMetaType object, but a QVariant of the specified type. Introduce a named constructor for this use case instead. In principle, this should lead to a deprecation of the QMetaType constructor... except that it's used everywhere, so I can't do it at this time. Drive-by, improve the documentation of the QVariant(QMetaType) constructor (since it's basically c&p for the new fromMetaType function). [ChangeLog][QtCore][QVariant] Added the QVariant::fromMetaType named constructor, that builds a QVariant of a given QMetaType. Change-Id: I4a499526bd0fe98eed0c1a3e91bcfc21efa9e352 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
41824a02cb
commit
4a6cbfbe5c
@ -516,7 +516,7 @@ void QVariant::create(int type, const void *copy)
|
|||||||
*/
|
*/
|
||||||
void QVariant::create(QMetaType type, const void *copy)
|
void QVariant::create(QMetaType type, const void *copy)
|
||||||
{
|
{
|
||||||
*this = QVariant(type, copy);
|
*this = QVariant::fromMetaType(type, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -910,27 +910,27 @@ void *QVariant::prepareForEmplace(QMetaType type)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Constructs variant of type \a type, and initializes with
|
Constructs a variant of type \a type, and initializes it with
|
||||||
\a copy if \a copy is not \nullptr.
|
a copy of \c{*copy} if \a copy is not \nullptr (in which case, \a copy
|
||||||
|
must point to an object of type \a type).
|
||||||
|
|
||||||
Note that you have to pass the address of the variable you want stored.
|
Note that you have to pass the address of the object you want stored.
|
||||||
|
|
||||||
Usually, you never have to use this constructor, use QVariant::fromValue()
|
Usually, you never have to use this constructor, use QVariant::fromValue()
|
||||||
instead to construct variants from the pointer types represented by
|
instead to construct variants from the pointer types represented by
|
||||||
\c QMetaType::VoidStar, and \c QMetaType::QObjectStar.
|
\c QMetaType::VoidStar, and \c QMetaType::QObjectStar.
|
||||||
|
|
||||||
If \a type does not support copy and default construction, the variant will
|
If \a type does not support copy construction and \a copy is not \nullptr,
|
||||||
be invalid.
|
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::fromValue(), QMetaType::Type
|
\sa QVariant::fromMetaType, QVariant::fromValue(), QMetaType::Type
|
||||||
*/
|
*/
|
||||||
QVariant::QVariant(QMetaType type, const void *copy) : d(type.iface())
|
QVariant::QVariant(QMetaType type, const void *copy)
|
||||||
|
: d()
|
||||||
{
|
{
|
||||||
type.registerType();
|
*this = fromMetaType(type, copy);
|
||||||
if (isValidMetaTypeForVariant(type.iface(), copy))
|
|
||||||
customConstruct(type.iface(), &d, copy);
|
|
||||||
else
|
|
||||||
d = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant::QVariant(int val) noexcept : d(std::piecewise_construct_t{}, val) {}
|
QVariant::QVariant(int val) noexcept : d(std::piecewise_construct_t{}, val) {}
|
||||||
@ -2711,6 +2711,41 @@ QT_WARNING_POP
|
|||||||
\overload
|
\overload
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 6.7
|
||||||
|
|
||||||
|
Creates a variant of type \a type, and initializes it with
|
||||||
|
a copy of \c{*copy} if \a copy is not \nullptr (in which case, \a copy
|
||||||
|
must point to an object of type \a type).
|
||||||
|
|
||||||
|
Note that you have to pass the address of the object you want stored.
|
||||||
|
|
||||||
|
Usually, you never have to use this constructor, use QVariant::fromValue()
|
||||||
|
instead to construct variants from the pointer types represented by
|
||||||
|
\c QMetaType::VoidStar, and \c QMetaType::QObjectStar.
|
||||||
|
|
||||||
|
If \a type does not support copy construction and \a copy is not \nullptr,
|
||||||
|
the variant will be invalid. Similarly, if \a copy is \nullptr and
|
||||||
|
\a type does not support default construction, the variant will be
|
||||||
|
invalid.
|
||||||
|
|
||||||
|
Returns the QVariant created as described above.
|
||||||
|
|
||||||
|
\sa QVariant::fromValue(), QMetaType::Type
|
||||||
|
*/
|
||||||
|
QVariant QVariant::fromMetaType(QMetaType type, const void *copy)
|
||||||
|
{
|
||||||
|
QVariant result;
|
||||||
|
type.registerType();
|
||||||
|
const auto iface = type.iface();
|
||||||
|
if (isValidMetaTypeForVariant(iface, copy)) {
|
||||||
|
result.d = Private(iface);
|
||||||
|
customConstruct(iface, &result.d, copy);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn template<typename T> T qvariant_cast(const QVariant &value)
|
\fn template<typename T> T qvariant_cast(const QVariant &value)
|
||||||
\relates QVariant
|
\relates QVariant
|
||||||
|
@ -539,7 +539,7 @@ public:
|
|||||||
// handle special cases
|
// handle special cases
|
||||||
using Type = std::remove_cv_t<T>;
|
using Type = std::remove_cv_t<T>;
|
||||||
if constexpr (std::is_null_pointer_v<Type>)
|
if constexpr (std::is_null_pointer_v<Type>)
|
||||||
return QVariant(QMetaType::fromType<std::nullptr_t>());
|
return QVariant::fromMetaType(QMetaType::fromType<std::nullptr_t>());
|
||||||
else if constexpr (std::is_same_v<Type, QVariant>)
|
else if constexpr (std::is_same_v<Type, QVariant>)
|
||||||
return std::forward<T>(value);
|
return std::forward<T>(value);
|
||||||
else if constexpr (std::is_same_v<Type, std::monostate>)
|
else if constexpr (std::is_same_v<Type, std::monostate>)
|
||||||
@ -586,6 +586,8 @@ public:
|
|||||||
return fromStdVariantImpl(std::move(value));
|
return fromStdVariantImpl(std::move(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QVariant fromMetaType(QMetaType type, const void *copy = nullptr);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool canConvert() const
|
bool canConvert() const
|
||||||
{ return canConvert(QMetaType::fromType<T>()); }
|
{ return canConvert(QMetaType::fromType<T>()); }
|
||||||
|
@ -442,11 +442,21 @@ void tst_QVariant::constructor()
|
|||||||
QVERIFY(var3.isNull());
|
QVERIFY(var3.isNull());
|
||||||
QVERIFY(var3.isValid());
|
QVERIFY(var3.isValid());
|
||||||
|
|
||||||
|
QVariant var3a = QVariant::fromMetaType(QMetaType::fromType<QString>());
|
||||||
|
QCOMPARE(var3a.typeName(), "QString");
|
||||||
|
QVERIFY(var3a.isNull());
|
||||||
|
QVERIFY(var3a.isValid());
|
||||||
|
|
||||||
QVariant var4 {QMetaType()};
|
QVariant var4 {QMetaType()};
|
||||||
QCOMPARE(var4.typeId(), QMetaType::UnknownType);
|
QCOMPARE(var4.typeId(), QMetaType::UnknownType);
|
||||||
QVERIFY(var4.isNull());
|
QVERIFY(var4.isNull());
|
||||||
QVERIFY(!var4.isValid());
|
QVERIFY(!var4.isValid());
|
||||||
|
|
||||||
|
QVariant var4a = QVariant::fromMetaType(QMetaType());
|
||||||
|
QCOMPARE(var4a.typeId(), QMetaType::UnknownType);
|
||||||
|
QVERIFY(var4a.isNull());
|
||||||
|
QVERIFY(!var4a.isValid());
|
||||||
|
|
||||||
QVariant var5(QLatin1String("hallo"));
|
QVariant var5(QLatin1String("hallo"));
|
||||||
QCOMPARE(var5.typeId(), QMetaType::QString);
|
QCOMPARE(var5.typeId(), QMetaType::QString);
|
||||||
QCOMPARE(var5.typeName(), "QString");
|
QCOMPARE(var5.typeName(), "QString");
|
||||||
@ -487,6 +497,14 @@ void tst_QVariant::constructor_invalid()
|
|||||||
QCOMPARE(variant.typeId(), int(QMetaType::UnknownType));
|
QCOMPARE(variant.typeId(), int(QMetaType::UnknownType));
|
||||||
QCOMPARE(variant.userType(), int(QMetaType::UnknownType));
|
QCOMPARE(variant.userType(), int(QMetaType::UnknownType));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, QRegularExpression("^Trying to construct an instance of an invalid type"));
|
||||||
|
QVariant variant = QVariant::fromMetaType(QMetaType(typeId));
|
||||||
|
QVERIFY(!variant.isValid());
|
||||||
|
QVERIFY(variant.isNull());
|
||||||
|
QCOMPARE(variant.typeId(), int(QMetaType::UnknownType));
|
||||||
|
QCOMPARE(variant.userType(), int(QMetaType::UnknownType));
|
||||||
|
}
|
||||||
{
|
{
|
||||||
QTest::ignoreMessage(QtWarningMsg, QRegularExpression("^Trying to construct an instance of an invalid type"));
|
QTest::ignoreMessage(QtWarningMsg, QRegularExpression("^Trying to construct an instance of an invalid type"));
|
||||||
QVariant variant(QMetaType(typeId), /* copy */ nullptr);
|
QVariant variant(QMetaType(typeId), /* copy */ nullptr);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user