summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@qt.io>2023-03-03 11:20:06 +0100
committerMarc Mutz <marc.mutz@qt.io>2023-03-24 06:40:11 +0100
commitde3e9708898da6a6480e973308d228b8dcc3b139 (patch)
treeac82c9c78221a96034884028fedcfcfa788cb9f3 /src
parent8570e86fff183ffa4c1dff577c7fa14e3342daee (diff)
Implement [variant.get] for QVariant [1/2]: get_if()
QVariant supports non-default-constructible payloads, in principle (QTBUG-105140). And fromValue() works with such types, but value() insists on providing a wide contract and therefore accidentally requires default-constructible. We can now invent other "Qt-ish" API like optional::value_or() or a value() that returns optional<T>, but we should first get the interface in that generic code must use, and which at the same time is the most versatile, because it gives write access to the element stored in the variant: [variant.get], consisting of get_if(), get(), and holds_alternative(). The latter is the same as get_if() != nullptr, so we won't provide it. This first patch implements get_if(), adds test for it. As a Hidden Friend supposed to be called with explicit template arguments, we run into the problem that wg21.link/P0846 solved for C++20. Add the usual work-around, and check it works. The ChangeLog will be on the last patch. Task-number: QTBUG-111598 Change-Id: I23f57ea2de3946944810c5552c68a7a3060a44f2 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/kernel/qvariant.cpp21
-rw-r--r--src/corelib/kernel/qvariant.h20
2 files changed, 39 insertions, 2 deletions
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index b25e855276..704b46e1c1 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -2333,7 +2333,7 @@ QPartialOrdering QVariant::compare(const QVariant &lhs, const QVariant &rhs)
Returns a pointer to the contained object as a generic void* that cannot be
written to.
- \sa QMetaType
+ \sa get_if(), QMetaType
*/
/*!
@@ -2343,7 +2343,7 @@ QPartialOrdering QVariant::compare(const QVariant &lhs, const QVariant &rhs)
This function detaches the QVariant. When called on a \l{isNull}{null-QVariant},
the QVariant will not be null after the call.
- \sa QMetaType
+ \sa get_if(), QMetaType
*/
void *QVariant::data()
{
@@ -2354,6 +2354,23 @@ void *QVariant::data()
}
/*!
+ \since 6.6
+ \fn template <typename T> const T* QVariant::get_if(const QVariant *v)
+ \fn template <typename T> T* QVariant::get_if(QVariant *v)
+
+ If \a v contains an object of type \c T, returns a pointer to the contained
+ object, otherwise returns \nullptr.
+
+ The overload taking a mutable \a v detaches \a v: When called on a
+ \l{isNull()}{null} \a v with matching type \c T, \a v will not be null
+ after the call.
+
+ These functions are provided for compatibility with \c{std::variant}.
+
+ \sa data()
+*/
+
+/*!
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.
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 990a2a0884..50b7e8c2bd 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -24,6 +24,8 @@
QT_BEGIN_NAMESPACE
+QT_ENABLE_P0846_SEMANTICS_FOR(get_if)
+
class QBitArray;
class QDataStream;
class QDate;
@@ -474,6 +476,24 @@ private:
}
QDebug qdebugHelper(QDebug) const;
#endif
+
+ template <typename T>
+ friend T *get_if(QVariant *v) noexcept
+ {
+ // data() will detach from is_null, returning non-nullptr
+ if (!v || v->d.type() != QMetaType::fromType<T>())
+ return nullptr;
+ return static_cast<T*>(v->data());
+ }
+ template <typename T>
+ friend const T *get_if(const QVariant *v) noexcept
+ {
+ // (const) data() will not detach from is_null, return nullptr
+ if (!v || v->d.is_null || v->d.type() != QMetaType::fromType<T>())
+ return nullptr;
+ return static_cast<const T*>(v->data());
+ }
+
template<typename T>
friend inline T qvariant_cast(const QVariant &);
protected: