1

I got a custom class Foo:

class Foo
{
public:
    // getters and setters
    // ...
private:
    QString string;
    QStringList list;
    int number;
}

The serialization of Foo has worked as expected:

QDataStream &operator<<(QDataStream &stream, const Foo &foo)
{
    stream<<foo.getString()<<foo.getList()<<foo.getNumber();
    return stream;
}

but when I attempted to serialize QList<Foo>, I got

error C2679: binary '<<' : no operator found which takes a right-hand operand of type “const Foo”

which directed to the corresponding Qt code (qdatastream.h):

template <typename T>
QDataStream& operator<<(QDataStream& s, const QList<T>& l)
{
    s << quint32(l.size());
    for (int i = 0; i < l.size(); ++i)
        s << l.at(i); // <--- compiler error here
    return s;
}

I know QList<T>::at() returns const T &, but I have no idea why it should fail to compile here. Please point out my error, I'd like to know how to fix this. Also, if I miss the necessary parts of code please do let me know. Thanks!

[Edit]: For reference, my environment is Qt 4.8.5 with MSVC2010/ Win 7 and I am using Qt creator.

Besides, this is how I serialize QList<Foo>:

QFile file("file.dat");
file.open(QIODevice::ReadWrite);
QDataStream out(&file);
out.setVersion(QDataStream::Qt_4_8);

out<<fooList; // It's the instant of QList<Foo> and it's not a pointer
//^^^^^^^^^^ compiler errors occurs as this line is added

[Last Edit]:

I finally figure out what's going on:

The operator overload that I defined to serialize Foo is written in a seperate .cpp file, where

QDataStream &operator<<(QDataStream &stream, const Foo &foo)
{
    stream<<foo.getString()<<foo.getList()<<foo.getNumber();
    return stream;
}

is inside foo.cpp.

The above code can be compiled but now I realize that it will never be used!

The serialization of QList<Foo> is implemented in another file notFoo.cpp, which is a "bigger class".

As I compile notFoo.cpp, only the definition and methods inside the header qdatastream.h could be found hence the error C2679 comes out, where:

template <typename T>
QDataStream& operator<<(QDataStream& s, const QList<T>& l)
{
    s << quint32(l.size());
    for (int i = 0; i < l.size(); ++i)
        s << l.at(i); // <--- compiler error here
    return s;
}

It shows that compiler doesn't know how to further serialze type Foo.

binary '<<' : no operator found which takes a right-hand operand of type “const Foo”

which means << of s << l.at(i); is not found (since I defined it in another .cpp file)

After I move the serialization method from Foo.cpp to notFoo.cpp, the code can finally be compiled.

[Conclusion]:

The compiler didn't find the function signature in the Foo.h since I define the stream operator inline within Foo.cpp.

Tay2510
  • 5,748
  • 7
  • 39
  • 58
  • 1
    Hm, strange, but this code works for me (Win7, Qt 4.8.5, MSVC9). – vahancho Apr 10 '14 at 06:37
  • It's weird. I've added more information to OP. – Tay2510 Apr 10 '14 at 06:49
  • What is `fooList` and how do you create and populate it? – vahancho Apr 10 '14 at 07:02
  • `QList fooList;` after that, `fooList.append(Foo);` My app appends `Foo` to `QList` at runtime. – Tay2510 Apr 10 '14 at 07:05
  • @vahancho I am not sure if this info. helps: I save `fooList` in an object. But I constantly get this error either I call a getter to return `fooList` to output datastream or I move `fooList` to `public` and directly call it through the instant. – Tay2510 Apr 10 '14 at 07:19
  • I think, if you show the complete code that triggers this error, it would help to understand the problem. – vahancho Apr 10 '14 at 07:25
  • @vahancho Thank you for your response. It's a medium size project and I am not sure which part I should emphasize but I will try making it as detailed as I can. – Tay2510 Apr 10 '14 at 07:38

1 Answers1

1

You need to declare the stream operator in the same header where you declare the serialized type:

// Foo.h
#include <QString>
#include <QDataStream>

class Foo
{
public:
    // getters and setters
    // ...
private:
    QString string;
    QStringList list;
    int number;
};

QDataStream &operator<<(QDataStream &stream, const Foo &foo);

Usually, the operator's implementation will be in the file where you implement Foo, but it could be in any .cpp file, really:

// Foo.cpp

Foo::Foo() {
  ...
}

...

QDataStream &operator<<(QDataStream &stream, const Foo &foo)
{
    stream<<foo.getString()<<foo.getList()<<foo.getNumber();
    return stream;
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313