Add qobject_cast operators for std::shared_ptr

Mimicking what we currently have for QSharedPointer, but also adding
* snake_case version (matching the ones in std)
* rvalue-overloaded versions (matching the C++2a overloads).

[ChangeLog][QtCore][QSharedPointer] Overloads of
qSharedPointerObjectCast have been added to work on std::shared_ptr.

Change-Id: I26ddffd82b000bf876e7c141fdce86a7b8c1d75a
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Giuseppe D'Angelo 2019-04-30 12:39:22 +02:00
parent 23c2da3cc2
commit d4435a37ca
3 changed files with 148 additions and 0 deletions

View File

@ -1299,6 +1299,57 @@
\sa QSharedPointer::objectCast(), qSharedPointerCast(), qSharedPointerConstCast()
*/
/*!
\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

View File

@ -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);

View File

@ -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()
{
{