How to overload the QDataStream &operator << and >> for third party libraries?



  • lets say I want to implement the QDataStream operator for "std::string"

    QDataStream &operator<<(QDataStream &ds, const std::string &inObj)
    {
    	ds << QString::fromStdString(inObj);
    	return ds;
    }
    
    QDataStream &operator >> (QDataStream &ds, std::string &outObj)
    {
    	QString outElement;
    	ds >> outElement;
    	outObj = outElement.toStdString();
    	return ds;
    }
    
    QDataStream &operator<<(QDataStream &ds, const MyClass &inObj)
    {
    	ds << QVector<std::string>::fromStdVector(inObj.myVector);
    }
    

    if I compile this and try to stream a std::string stored inside a QVector I will get the following error:

    binary '<<': no operator found which takes a left-hand operand of type 'QDataStream'
    

    How can I make the QDataStream class see the operator that I overloaded for std::string?

    If I stream a std::string that in not included in a QVector then it will be streamed correctly.

    I'm just taking std::string as an example, but it could be any other class declared on a third party library


  • Moderators

    @robson-estek
    where did you put this code?
    in a header file you include or in a cpp file?



  • @raven-worx

    in the MyClass.h inside my namespace

    namespace myNamespace
    {
    class MyClass.h
    {
    ...
    		friend QDataStream &operator << (QDataStream &ds, const std::string &inObj);
    		friend QDataStream &operator >> (QDataStream &ds, std::string &outObj);
    friend QDataStream &operator<<(QDataStream &ds, const MyClass &inObj);
    ...
    }
    }
    

    and in the MyClass.cpp inside my namespace i've put the rest

    QDataStream &operator<<(QDataStream &ds, const MyClass &inObj)
    {
    	ds << QVector<std::string>::fromStdVector(inObj.myVector);
    }


    • You need to declare the std::string operators in an header and include the header in MyClass.cpp
    • QVector<std::string>::fromStdVector is inefficient, it takes a deep copy, just serialise the size and each of the values separatley
    • you don't need to friend the std::string operator
    • global friends usually have the global scope expicited `friend QDataStream& (::operator<<) (QDataStream &ds, const MyClass &inObj);


  • @VRonin

    thank you,

    I was thinking about doing what you said, but I hoped that there was a way more pleasent to the eye =).

    So to make std::vector< std::string > be recognized by the QDataStream, is declaring the operators << and >> with "std::vectorstd::string" as the parameter the only option?



  • No.

    stringserial.h

    QDataStream &operator<<(QDataStream &ds, const std::string &inObj);
    QDataStream &operator >> (QDataStream &ds, std::string &outObj);
    

    stringserial.cpp

    #include "stringserial.h"
    QDataStream &operator<<(QDataStream &ds, const std::string &inObj)
    {
    	ds << QString::fromStdString(inObj);
    	return ds;
    }
    
    QDataStream &operator >> (QDataStream &ds, std::string &outObj)
    {
    	QString outElement;
    	ds >> outElement;
    	outObj = outElement.toStdString();
    	return ds;
    }
    

    myclass.h

    namespace myNamespace{
    class MyClass{
    // other stuff
    std::vector<std::string> inObj;
    friend QDataStream& (::operator<<) (QDataStream &ds, const MyClass &inObj);
    friend QDataStream& (::operator>>) (QDataStream &ds, MyClass &inObj);
    };
    }
    QDataStream& operator<<(QDataStream &ds, const myNamespace::MyClass &inObj);
    QDataStream& operator>>(QDataStream &ds, myNamespace::MyClass &inObj);
    

    myclass.cpp

    #include "myclass.h"
    #include "stringserial.h"
    // other stuff
    QDataStream& operator<<(QDataStream &ds, const myNamespace::MyClass &inObj)
    {
    	ds << ststic_cast<quint32>(inObj.myVector.size());
    for(auto& vecElement : inObj.myVector)
    ds << vecElement;
    return ds;
    }
    QDataStream& operator>>(QDataStream &ds, myNamespace::MyClass &inObj)
    {
    quint32 tempSize
    	ds >> tempSize; 
    inObj.myVector.resize(tempSize);
    for(quint32 i=0;i<tempSize;++i)
    ds >> inObj.myVector[i];
    return ds;
    }
    


  • @VRonin

    thank you again for your time, I did understood the concept of writing/reading the size of the vector first and then writing/reading the elements of the vector.

    But what I am interested, just to know if it is possible, I wanted something like

    QDataStream& operator<<(QDataStream &ds, const myNamespace::MyClass &inObj)
    {
    	ds << inObj.myStdStringVector;
            return ds;
    }
    

    if I understood correctly, the only way to achieve that is by doing something like

    QDataStream& operator<<(QDataStream &ds, const std::vector<std::string> &inVector)
    {
            ds << qInt32(inVector.size());
    	for(size_t i = 0; i<inVector.size(); i++)
                 ds << inVector[i];
            return ds;
    }
    

Log in to reply
 

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