0

I have created a class (MyNodeClass) and now want to add serialization capabilities. I declare (in mynodeclass.h) my serialization methods as follows:

#ifndef MYNODECLASS_H
#define MYNODECLASS_H

#include <QString>
#include <QVariant>
#include <QDataStream>
#include <QReadWriteLock>


namespace NS { class MyNodeClass; }
QDataStream& operator<<(QDataStream &out, const MyNodeClass &node);
QDataStream& operator>>(QDataStream &in, MyNodeClass &node);


namespace NS {

class MyNodeClass
{
public:
    MyNodeClass(quint64 parent, QString name, MyNodeClass::MyEnum type);
    friend QDataStream& operator<<(QDataStream &out, const MyNodeClass &node);
    friend QDataStream& operator>>(QDataStream &in, MyNodeClass &node);

private:
    quint64 m_parent;
    QString m_name;
    int m_type;
    QVariant m_content;
    QReadWriteLock m_lock;
};
}

#endif // MYNODECLASS_H

My definitions (in mynodeclass.cpp) are:

 #include "mynodeclass.h"


QDataStream& operator<<(QDataStream &out, const NS::MyNodeClass &node) {
    out
            << node.m_name
            << node.m_type
            << node.m_parent
            << node.m_content;
    return out;
}


QDataStream& operator>>(QDataStream &in, NS::MyNodeClass &node) {
    QString name;
    int type;
    quint64 parent;
    QVariant contents;

    in
            >> name
            >> type
            >> parent
            >> contents;
    node = NS::MyNodeClass(parent,name,type);

    return in;
}

using namespace NS;

MyNodeClass::MyNodeClass(quint64 parent, QString name, MyNodeClass::MyEnum type) {}

The compiler complains that my operator<< cannot access private members of NS::MyNodeClass. That means the signatures aren't lining up. I've tried every combination of namespace related changes but can't figure it out. I've modelled my code after this post

How should the friend functions be defined so that there is no complaint about namespace or access to private members? (Please note that all examples I could find use a single file, so splitting into .h and .cpp is part of what needs to be addressed)

TSG
  • 4,242
  • 9
  • 61
  • 121
  • You could do one better. Make it a [mre]. – Ted Lyngmo Jan 31 '21 at 02:58
  • The good thing about a MRE is that we can copy, compile and give you immediate feedback. Most of us are used to using debugging tools and when I start looking at a problem, i throw it in the debugger and see what is says. – Ted Lyngmo Jan 31 '21 at 03:10
  • I found a SO post explaning problems in streaming enum type so I eliminated that part of question. Remaining part of question relates to namespaces, so I clarified question – TSG Jan 31 '21 at 04:22
  • Your header declares `ns::operator<<` as a friend of `MyNodeClass`; this function is never defined. Your source file defines `::operator<<` (in global namespace) - this function was not declared a friend of `MyNodeClass`, and so cannot access its private members. Defining these functions in namespace `ns` is the right thing to do - can you show the warnings produced when you try that? – Igor Tandetnik Jan 31 '21 at 04:31
  • I have reworked the code per another posts which suggests how to solve this. But still have namespace issues. – TSG Jan 31 '21 at 04:57

1 Answers1

0

You declare 2 operator >> in different namespace, only the one in namespace NS is friend.

get rid of your "forward declarations":

// Remove that
namespace NS { class MyNodeClass; }
QDataStream& operator<<(QDataStream &out, const MyNodeClass &node);
QDataStream& operator>>(QDataStream &in, MyNodeClass &node);

and implement NS::operator<<:

namespace NS {

QDataStream& operator<<(QDataStream &out, const NS::MyNodeClass &node) {
    return out << node.m_name
               << node.m_type
               << node.m_parent
               << node.m_content;
}

QDataStream& operator>>(QDataStream &in, NS::MyNodeClass &node) {
    QString name;
    int type;
    quint64 parent;
    QVariant contents;

    in >> name
       >> type
       >> parent
       >> contents;
    node = NS::MyNodeClass(parent, name, type);

    return in;
}


MyNodeClass::MyNodeClass(quint64 parent, QString name, MyNodeClass::MyEnum type) {}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • You have removed friend in front of operator definitions - mine won't compile with out. Why? Aren't those necessary to access private members, and, so compiler doesn't think we are overloading bitwise shift? – TSG Jan 31 '21 at 19:24
  • With friend added it compiles, but when I try to serialize runtime message QVariant unable to save type NS::MyNodeClass. Is there anything missing in terms of registering a meta type etc? – TSG Jan 31 '21 at 19:29