Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
178 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
#ifndef QOBJECTUNIQUEPTR_H | ||
#define QOBJECTUNIQUEPTR_H | ||
|
||
#include <qsharedpointer.h> | ||
#include <qtypeinfo.h> | ||
|
||
class QVariant; | ||
|
||
template <class T> | ||
class QObjectUniquePtr | ||
{ | ||
Q_STATIC_ASSERT_X( !std::is_pointer<T>::value, "QObjectUniquePtr's template type must not be a pointer type" ); | ||
|
||
template<typename U> | ||
struct TypeSelector | ||
{ | ||
typedef QObject Type; | ||
}; | ||
template<typename U> | ||
struct TypeSelector<const U> | ||
{ | ||
typedef const QObject Type; | ||
}; | ||
typedef typename TypeSelector<T>::Type QObjectType; | ||
QWeakPointer<QObjectType> wp; | ||
public: | ||
inline QObjectUniquePtr() { } | ||
inline QObjectUniquePtr( T *p ) : wp( p ) { } | ||
// compiler-generated copy/move ctor/assignment operators are fine! | ||
|
||
~QObjectUniquePtr() { delete wp.data(); } | ||
|
||
inline void swap( QObjectUniquePtr &other ) { wp.swap( other.wp ); } | ||
|
||
inline QObjectUniquePtr<T> &operator=( T *p ) | ||
{ wp.assign( static_cast<QObjectType *>( p ) ); return *this; } | ||
|
||
inline T *data() const | ||
{ return static_cast<T *>( wp.data() ); } | ||
inline T *operator->() const | ||
{ return data(); } | ||
inline T &operator*() const | ||
{ return *data(); } | ||
inline operator T *() const | ||
{ return data(); } | ||
|
||
inline bool isNull() const | ||
{ return wp.isNull(); } | ||
|
||
inline void clear() | ||
{ wp.clear(); } | ||
|
||
T *release() { T *p = qobject_cast<T *>( wp.data() ); wp.clear(); return p; } | ||
|
||
void reset( T *p = nullptr ) { delete wp.data(); wp = p; } | ||
}; | ||
template <class T> Q_DECLARE_TYPEINFO_BODY( QObjectUniquePtr<T>, Q_MOVABLE_TYPE ); | ||
|
||
template <class T> | ||
inline bool operator==( const T *o, const QObjectUniquePtr<T> &p ) | ||
{ return o == p.operator->(); } | ||
|
||
template<class T> | ||
inline bool operator==( const QObjectUniquePtr<T> &p, const T *o ) | ||
{ return p.operator->() == o; } | ||
|
||
template <class T> | ||
inline bool operator==( T *o, const QObjectUniquePtr<T> &p ) | ||
{ return o == p.operator->(); } | ||
|
||
template<class T> | ||
inline bool operator==( const QObjectUniquePtr<T> &p, T *o ) | ||
{ return p.operator->() == o; } | ||
|
||
template<class T> | ||
inline bool operator==( const QObjectUniquePtr<T> &p1, const QObjectUniquePtr<T> &p2 ) | ||
{ return p1.operator->() == p2.operator->(); } | ||
|
||
template <class T> | ||
inline bool operator!=( const T *o, const QObjectUniquePtr<T> &p ) | ||
{ return o != p.operator->(); } | ||
|
||
template<class T> | ||
inline bool operator!= ( const QObjectUniquePtr<T> &p, const T *o ) | ||
{ return p.operator->() != o; } | ||
|
||
template <class T> | ||
inline bool operator!=( T *o, const QObjectUniquePtr<T> &p ) | ||
{ return o != p.operator->(); } | ||
|
||
template<class T> | ||
inline bool operator!= ( const QObjectUniquePtr<T> &p, T *o ) | ||
{ return p.operator->() != o; } | ||
|
||
template<class T> | ||
inline bool operator!= ( const QObjectUniquePtr<T> &p1, const QObjectUniquePtr<T> &p2 ) | ||
{ return p1.operator->() != p2.operator->() ; } | ||
|
||
template<typename T> | ||
QObjectUniquePtr<T> | ||
QObjectUniquePtrFromVariant( const QVariant &variant ) | ||
{ | ||
return QObjectUniquePtr<T>( qobject_cast<T *>( QtSharedPointer::weakPointerFromVariant_internal( variant ).data() ) ); | ||
} | ||
|
||
#endif // QOBJECTUNIQUEPTR_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/*************************************************************************** | ||
testqobjectuniqueptr.cpp | ||
-------------------------------------- | ||
Date : | ||
Copyright : (C) 2019 by Matthias Kuhn | ||
Email : matthias@opengis.ch | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#include "qgstest.h" | ||
#include "qobjectuniqueptr.h" | ||
|
||
#include "qgstest.h" | ||
|
||
class TestQObjectUniquePtr : public QObject | ||
{ | ||
Q_OBJECT | ||
|
||
private slots: | ||
void testMemLeak(); | ||
void testParentDeletedFirst(); | ||
void testParentDeletedAfter(); | ||
}; | ||
|
||
|
||
|
||
void TestQObjectUniquePtr::testMemLeak() | ||
{ | ||
QObject *myobj = new QObject(); | ||
QObjectUniquePtr<QObject> obj( myobj ); | ||
} | ||
|
||
void TestQObjectUniquePtr::testParentDeletedFirst() | ||
{ | ||
QObject *parent = new QObject(); | ||
QObject *child = new QObject( parent ); | ||
|
||
QObjectUniquePtr<QObject> obj( child ); | ||
QVERIFY( !obj.isNull() ); | ||
|
||
delete parent; | ||
QVERIFY( obj.isNull() ); | ||
} | ||
|
||
void TestQObjectUniquePtr::testParentDeletedAfter() | ||
{ | ||
QObject *parent = new QObject(); | ||
QObject *child = new QObject( parent ); | ||
QPointer<QObject> observer( child ); | ||
|
||
{ | ||
QObjectUniquePtr<QObject> obj( child ); | ||
QVERIFY( !observer.isNull() ); | ||
} | ||
QVERIFY( observer.isNull() ); | ||
|
||
|
||
// Basically shouldn't crash because of double delete on this line | ||
delete parent; | ||
QVERIFY( observer.isNull() ); | ||
} | ||
|
||
QGSTEST_MAIN( TestQObjectUniquePtr ) | ||
#include "testqobjectuniqueptr.moc" |