0

Since Qt uses its horrible archaic ptr mechanisms, using their QSharedPointer is mostly not practical. The moment you set a QSharedPointer to nullptr while being in a slot could very well result in undefined behavior (crashing). Also, the design of QSharedPointer does have the wrong design decisions in contrast to std::shared_ptr. So I thought about a proper shared pointer, which could be used also in slots.

What I came up is the following:

template <typename T>
struct LateDeleter {
    void operator()( T* ptr ) {
        if( !ptr )
            return;
        auto qObject = static_cast<QObject*>( ptr );
        qObject->deleteLater();
    }
};

template <typename T>
class QSharedPtr : public std::shared_ptr<T> {
public:
    typedef std::shared_ptr<T> __base;
#ifdef Q_OS_WIN
    QSharedPtr() : __base( nullptr, LateDeleter<T>() ) {}
#else
    constexpr QSharedPtr() : __base( nullptr, LateDeleter<T>() ) {}
#endif
    template< class Y >
    explicit QSharedPtr( Y* ptr ) : __base( ptr, LateDeleter<T>() ) {}
#ifdef Q_OS_WIN
    QSharedPtr( std::nullptr_t ) : __base( nullptr, LateDeleter<T>() ) {}
#else
    constexpr QSharedPtr( std::nullptr_t ) : __base( nullptr, LateDeleter<T>() ) {}
#endif
    template< class Y >
    QSharedPtr( const QSharedPtr<Y>& r ) : __base( r ) {}
    QSharedPtr( QSharedPtr&& r ) : __base( std::forward<QSharedPtr>(r) ) {}
    template< class Y >
    QSharedPtr( QSharedPtr<Y>&& r ) : __base( std::forward<QSharedPtr<Y>>(r) ) {}
};

#ifdef Q_OS_WIN
// Hacky solution for VS2010
template<class _Ty, class T1>
QSharedPtr<_Ty> makeShared( T1&& arg1 ) {   // make a shared_ptr
    auto ptr = new _Ty( std::forward<T1>(arg1) );
    return QSharedPtr<_Ty>( ptr );
}
#else
// Use proper variadic template arguments
template <class T, class... Args>
QSharedPtr<T> makeShared( Args&&... args ) {
    auto ptr = new T( std::forward<Args>(args)... );
    return QSharedPtr<T>( ptr );
}
#endif

While this seems to work great, I wonder whether there are further pitfalls, I have not thought about. Also would appreciate comments about this approach.

demonplus
  • 5,613
  • 12
  • 49
  • 68
abergmeier
  • 13,224
  • 13
  • 64
  • 120
  • 1
    Could you please tell me more about wrong design of `QSharedPointer` and mentioned slots related issues or provide any link? – Pavel Strakhov Jun 25 '13 at 19:03
  • I guess you refer to issues like discussed here: http://stackoverflow.com/questions/4888189/how-delete-and-deletelater-works-wrt-to-signals-and-slots-in-qt/4889395#4889395 Your approach might help there in a couple situations, although managing QObjects with shared ptrs will still fail when requiring QObject parent-child hierachies. The latter using raw pointers just doesn't go well with shared ptr usage. – Frank Osterfeld Jun 25 '13 at 20:02
  • I'd probably go for queued connections in the cases where the slot must delete the emitter. – Frank Osterfeld Jun 25 '13 at 20:06
  • @FrankOsterfeld Sure, when you are caught in parent-child mechanism, a shared pointer is not an option. Since we avoid this mechanism like the plague, using managed pointers works quite well for us. – abergmeier Jun 26 '13 at 06:17
  • This question appears to be off-topic because the OP doesn't have an issue right now aside of a [code review](http://codereview.stackexchange.com/) – UmNyobe Mar 01 '14 at 11:23

0 Answers0