This is the basic code structure (I'll reveal more if it becomes relevant to the problem):
class Outer {
// Forward declaration for the next forward declaration
template <class C> class Inner;
// Forward declaration for the actual Inner class definition
template <class C>
friend std::ostream& operator<<(std::ostream &os, const Inner<C> &obj);
template <class C>
class Inner {
friend std::ostream& operator<< <>(std::ostream &os, const Inner &obj);
};
};
Since the inner class is templated, I realized my operator<<
override had to be as well. Additionally, the second friend
declaration is a template instantiation, so that operator<< <C>
is only friends with Outer::Inner<C>
.
When I define the operator override in the separate implementation file, it looks like this:
template <class C>
std::ostream& operator<<(std::ostream &os, const Outer::Inner<C> &obj) {
// definition
}
Over the past several days, I have repeatedly refactored my code to a ridiculous degree in the hopes of making this work. Most recently, I tried only compiling *.h
on g++ and received three error messages all for the same line (the one with the template instantiation).
outer.h:x:y1: error: declaration of ‘operator<<’ as non-function
friend std::ostream& operator<< <>(std::ostream &os, const Inner &obj);
^~
outer.h:x:y1: error: expected ‘;’ at end of member declaration
outer.h:x:y2: error: expected unqualified-id before ‘<’ token
friend std::ostream& operator<< <>(std::ostream &os, const Inner &obj);
^
Despite extensively searching the phrases given in the error output, however, I'm still no closer to solving this, so I'd be grateful if someone with C++ experience, who unlike me knows what they're doing, could please help.
After much more research, I am convinced that this specific case is actually impossible—an operator
overload generally can't be a friend of a class that is both nested and templated. (If you think that's wrong, please let me know why, since I'm far from being a C++ expert myself.)
I've tried many, many different solutions to this, and while I don't think it would be very productive to write a detailed account of every method I tried and the specific reasons for their failures, some of the errors included
class Outer
Outer::Inner<
[Type]>
operator<<
operator<<
in addition to the ones in the original post.
So in this area of my code, I'm ditching the operator<<
approach. My less elegant but immediately effective alternative:
class Outer {
template <class C>
class Inner {
public:
std::ostream& printout(std::ostream &os) {
os << /* whatever */ << /* I want */ << /* to print */;
return os;
}
};
};
Some potentially helpful links: