Dragging std::shared_ptr



  • Greetings. I want to use drag-and-drop to drag a QTreeWidgetItem that has std::shared_ptr user data. Qt is throwing an exception because it doesn't know how to store the shared_ptr onto a QDataStream. I read a bit and it seems that Q_DECLARE_SMART_POINTER_METATYPE is supposed to allow this to work. However, I have not had any success. I have built a tiny example showing the problem. Does anyone know how to do this properly?

    In case you're wondering, I need to use shared_ptr (as opposed to other Qt shared pointers) because the pointer comes from a non-Qt part of the application (which I cannot control). I'm not comfortable converting the shared pointer to a raw pointer because it could go out of scope during my operation.

    Thank you.

    // DragSharedPtr.cpp
    
    #include <QtGlobal>
    #include <QMetaType>
    #include <QVariant>
    #include <QDataStream>
    
    #include <memory>
    
    Q_DECLARE_SMART_POINTER_METATYPE(std::shared_ptr)
    Q_DECLARE_METATYPE(std::shared_ptr<int>);
    
    
    int main()
    {
        qRegisterMetaType< std::shared_ptr<int> >();
    
        // create variant holding the shared pointer (this works)
        auto spint = std::make_shared<int>(42);
        QVariant varspint = QVariant::fromValue(spint);
    
        // get the shared pointer back (this works)
        auto spint2 = varspint.value<std::shared_ptr<int>>();
        Q_ASSERT(spint2 == spint);
    
        // Try to encode the variant into a stream.  This is
        // needed when, for example, dragging the variant.
        //
        // This code compiles, but fails with a console warning:
        //
        //     QVariant::save: unable to save type  
        //                     'std:;shard_ptr<int>' (type id: 1024)
        //
        // and an exception:
        //    
        //     Program: <path to Qt>\bin\Qt5Cored.dll
        //     Module: 5.5.1
        //     File: <path to Qt>\src\corelib\global\qglobal.cpp
        //     Line: 2974
        //     ASSERT failure in QVariant::save: "Invalid type to save", 
        //            file <path...>\qvariant.cpp, line 2124
        //    
        QByteArray encoded;
        QDataStream stream(&encoded, QIODevice::WriteOnly);
        stream << varspint;
    
        return 0;
    }
    

  • Moderators

    You have to implement QDataStream & QDataStream::operator<<(std::shared_ptr<int>) and QDataStream & QDataStream::operator>>(std::shared_ptr<int>&). I don't see any other possibility, because QDataStream does not know how to serialize/deserialize a std::sgared_ptr.



  • Thanks. Yes, I ended up doing just that. I'm a bit concerned about lifetime of ownership, but I don't see a better way.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.