summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/tools/qsharedpointer.cpp51
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h42
-rw-r--r--tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp55
3 files changed, 148 insertions, 0 deletions
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
index 62b76c5bb7..0aedf4c6d6 100644
--- a/src/corelib/tools/qsharedpointer.cpp
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -1300,6 +1300,57 @@
*/
/*!
+ \fn template <class X, class T> std::shared_ptr<X> qSharedPointerObjectCast(const std::shared_ptr<T> &src)
+ \relates QSharedPointer
+ \since 5.14
+
+ Returns a shared pointer to the pointer held by \a src, using a
+ \l qobject_cast() to type \tt X to obtain an internal pointer of the
+ appropriate type. If the \tt qobject_cast fails, the object
+ returned will be null.
+
+ Note that \tt X must have the same cv-qualifiers (\tt const and
+ \tt volatile) that \tt T has, or the code will fail to
+ compile. Use const_pointer_cast to cast away the constness.
+*/
+
+/*!
+ \fn template <class X, class T> std::shared_ptr<X> qobject_pointer_cast(const std::shared_ptr<T> &src)
+ \relates QSharedPointer
+ \since 5.14
+
+ Same as qSharedPointerObjectCast(). This function is provided for STL
+ compatibility.
+*/
+
+/*!
+ \fn template <class X, class T> std::shared_ptr<X> qSharedPointerObjectCast(std::shared_ptr<T> &&src)
+ \relates QSharedPointer
+ \since 5.14
+
+ Returns a shared pointer to the pointer held by \a src, using a
+ \l qobject_cast() to type \tt X to obtain an internal pointer of the
+ appropriate type.
+
+ If the \tt qobject_cast succeeds, the function will return a valid shared
+ pointer, and \a src is reset to null. If the \tt qobject_cast fails, the
+ object returned will be null, and \a src will not be modified.
+
+ Note that \tt X must have the same cv-qualifiers (\tt const and
+ \tt volatile) that \tt T has, or the code will fail to
+ compile. Use const_pointer_cast to cast away the constness.
+*/
+
+/*!
+ \fn template <class X, class T> std::shared_ptr<X> qobject_pointer_cast(std::shared_ptr<T> &&src)
+ \relates QSharedPointer
+ \since 5.14
+
+ Same as qSharedPointerObjectCast(). This function is provided for STL
+ compatibility.
+*/
+
+/*!
\fn template <class X> template <class T> QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
\relates QSharedPointer
\relates QWeakPointer
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index 81d8dcd839..0851121ff2 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -67,6 +67,8 @@ QT_END_NAMESPACE
#endif
#include <QtCore/qhashfunctions.h>
+#include <memory>
+
QT_BEGIN_NAMESPACE
@@ -996,6 +998,46 @@ qSharedPointerFromVariant(const QVariant &variant)
return qSharedPointerObjectCast<T>(QtSharedPointer::sharedPointerFromVariant_internal(variant));
}
+// std::shared_ptr helpers
+
+template <typename X, class T>
+std::shared_ptr<X> qobject_pointer_cast(const std::shared_ptr<T> &src)
+{
+ using element_type = typename std::shared_ptr<X>::element_type;
+ return std::shared_ptr<X>(src, qobject_cast<element_type *>(src.get()));
+}
+
+template <typename X, class T>
+std::shared_ptr<X> qobject_pointer_cast(std::shared_ptr<T> &&src)
+{
+ using element_type = typename std::shared_ptr<X>::element_type;
+ auto castResult = qobject_cast<element_type *>(src.get());
+ if (castResult) {
+ auto result = std::shared_ptr<X>(std::move(src), castResult);
+#if __cplusplus <= 201703L
+ // C++2a's move aliasing constructor will leave src empty.
+ // Before C++2a we don't really know if the compiler has support for it.
+ // The move aliasing constructor is the resolution for LWG2996,
+ // which does not impose a feature-testing macro. So: clear src.
+ src.reset();
+#endif
+ return result;
+ }
+ return std::shared_ptr<X>();
+}
+
+template <typename X, class T>
+std::shared_ptr<X> qSharedPointerObjectCast(const std::shared_ptr<T> &src)
+{
+ return qobject_pointer_cast<X>(src);
+}
+
+template <typename X, class T>
+std::shared_ptr<X> qSharedPointerObjectCast(std::shared_ptr<T> &&src)
+{
+ return qobject_pointer_cast<X>(std::move(src));
+}
+
#endif
template<typename T> Q_DECLARE_TYPEINFO_BODY(QWeakPointer<T>, Q_MOVABLE_TYPE);
diff --git a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp
index 19b2aa02f3..3e87a506bf 100644
--- a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp
+++ b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp
@@ -78,6 +78,7 @@ private slots:
void sharedPointerFromQObjectWithWeak();
void weakQObjectFromSharedPointer();
void objectCast();
+ void objectCastStdSharedPtr();
void differentPointers();
void virtualBaseDifferentPointers();
#ifndef QTEST_NO_RTTI
@@ -1113,6 +1114,60 @@ void tst_QSharedPointer::objectCast()
safetyCheck();
}
+
+void tst_QSharedPointer::objectCastStdSharedPtr()
+{
+ {
+ OtherObject *data = new OtherObject;
+ std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data);
+ QVERIFY(baseptr.get() == data);
+
+ // perform successful object cast
+ std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(baseptr);
+ QVERIFY(ptr.get());
+ QVERIFY(ptr.get() == data);
+
+ QVERIFY(baseptr.get() == data);
+ }
+
+ {
+ OtherObject *data = new OtherObject;
+ std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data);
+ QVERIFY(baseptr.get() == data);
+
+ // perform successful object cast
+ std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(std::move(baseptr));
+ QVERIFY(ptr.get());
+ QVERIFY(ptr.get() == data);
+
+ QVERIFY(!baseptr.get());
+ }
+
+ {
+ QObject *data = new QObject;
+ std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data);
+ QVERIFY(baseptr.get() == data);
+
+ // perform unsuccessful object cast
+ std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(baseptr);
+ QVERIFY(!ptr.get());
+
+ QVERIFY(baseptr.get() == data);
+ }
+
+ {
+ QObject *data = new QObject;
+ std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data);
+ QVERIFY(baseptr.get() == data);
+
+ // perform unsuccessful object cast
+ std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(std::move(baseptr));
+ QVERIFY(!ptr.get());
+
+ QVERIFY(baseptr.get() == data);
+ }
+}
+
void tst_QSharedPointer::differentPointers()
{
{