3

In the C++ namespace myspace I have a class Outer which in turn has an inner class Inner. While I can declare and define a global friend operator QDataStream& operator<<(QDataStream& s, const myspace::Outer& o), I cannot see how to declare a global friend operator QDataStream& operator<<(QDataStream& s, const myspace::Outer::Inner& o). The commented out lines represent a failed attempt. I do not see how to declare the inner class without defining the outer.

namespace myspace {
    class Outer;
    //class Outer::Inner;
}

QDataStream& operator<<(QDataStream& s, const myspace::Outer& o);
//QDataStream& operator<<(QDataStream& s, const myspace::Outer::Inner& o);


namespace myspace {

    class Outer {

        friend QDataStream& (::operator <<)(QDataStream&, const Outer&);

        class Inner {
            //friend QDataStream& (::operator <<)(QDataStream&, const Inner&);
            int i;
        };

        int o;
    };

}

I have read Namespaces and operator resolution, C++ Defining the << operator of an inner class, Accessing private class in operator<< in namespace and Operator overloading, name resolution and namespaces, but none seem to work.

If I uncomment these lines, the first gives the error message "outer.h:7: error: 'Inner' in 'class myspace::Outer' does not name a type class Outer::Inner; ^" This seems to be the key. I cannot declare the inner class.

I am using C++ 11.

This question is not a duplicate of Forward declaration of nested types/classes in C++ if it can can be solved without forward reference.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
fundagain
  • 398
  • 1
  • 6
  • 23
  • Can you add error messages you get when you try to compile with the failed attempts ? – HatsuPointerKun Jul 26 '17 at 18:45
  • I added the error message when the first commented line is uncommented. – fundagain Jul 26 '17 at 18:52
  • You are correct, this is a duplicate. It seems it is impossible in C++. – fundagain Jul 26 '17 at 19:02
  • *This is not a duplicate - not forward declaration needed* There is a simple solution which I cannot add because of the duplicate mark: namespace myspace { class Outer { friend QDataStream& operator<<(QDataStream&, const Outer&); public: class Inner { friend QDataStream& operator<<(QDataStream&, const Inner&); int i; }; private: int o; }; QDataStream& operator<<(QDataStream& s, const myspace::Outer& o) { s << o.o; return s; } QDataStream& operator<<(QDataStream& s, const myspace::Outer::Inner& i) { s << i.i; return s; } } – Andreas H. Jul 26 '17 at 19:15
  • @AndreasH you need to make the Inner class `public`. It is `private` in the original contents. There is no solution in this case. But I agree, it is not an exact duplicate. – Serge Jul 26 '17 at 19:25
  • You do not have to make the inner class public. You can also make operator<<(QDataStream& s, const myspace::Outer::Inner& i) a friend for the Outer and the Inner class. This way the operator definition works without making Inner a public type. – Andreas H. Jul 26 '17 at 19:29
  • try this (no public keyword and perfectly working): `namespace myspace { class Outer { class Inner { friend QDataStream& operator<<(QDataStream&, const Inner&); int i; }; friend QDataStream& operator<<(QDataStream&, const Outer&); friend QDataStream& operator<<(QDataStream&, const Inner&); int o; }; QDataStream& operator<<(QDataStream& s, const myspace::Outer& o) { s << o.o; return s; } QDataStream& operator<<(QDataStream& s, const myspace::Outer::Inner& i) { s << i.i; return s; } }` – Andreas H. Jul 26 '17 at 19:30
  • Thank you Andreas H. Your solution works perfectly. I panicked when the Duplicate was thrown at me, since I could not see a non forward reference approach. I will re-ask the question, since the problem is real and you solved it. – fundagain Jul 28 '17 at 17:19
  • Yes AndreasH. Your solution works! Thank you. I was on the verge of de-encapsulating! – fundagain Jul 28 '17 at 17:52
  • Reopened @AndreasH. – Michael Myers Jul 28 '17 at 20:54

1 Answers1

0

Given the time lapse, I am posting the correct answer given by Andreas H.

namespace myspace {
class Outer {
    class Inner {
        friend QDataStream& operator<<(QDataStream&, const Inner&);
        int i;
    };
    friend QDataStream& operator<<(QDataStream&, const Outer&);
    friend QDataStream& operator<<(QDataStream&, const Inner&);
    int o;
};
QDataStream& operator<<(QDataStream& s, const myspace::Outer& o) {
    s << o.o;
    return s;
}
QDataStream& operator<<(QDataStream& s, const myspace::Outer::Inner& i) {
    s << i.i;
    return s;
}
}
fundagain
  • 398
  • 1
  • 6
  • 23