It compiled without complaining on VC++..
I looked at the standard and found (section 11.4, part 9)
If a friend declaration appears in a local class (9.8) and the name specified is an unqualified name, a prior
declaration is looked up without considering scopes that are outside the innermost enclosing non-class
scope. For a friend function declaration, if there is no prior declaration, the program is ill-formed. For a
friend class declaration, if there is no prior declaration, the class that is specified belongs to the innermost
enclosing non-class scope, but if it is subsequently referenced, its name is not found by name lookup until a
matching declaration is provided in the innermost enclosing nonclass scope.
section 9.8 says
A class can be defined within a function definition; such a class is called a local class.
btw, do you happen to know why we need both Line 10 and Line 16?
I suppose Line 10 doesn't count as a declaration?
correct.
Also when an unqualified friend function (not qualified with a namespace) is given like that - the compiler assumes that the firend function is in the nearest enclosing namespace of the class - hence the need to
declare the friend function in the foo namespace (as that is the nearest enclosing namespace)
To put the friend function in the global namespace - this should do the trick:
#include <iostream>
usingnamespace std;
//forward declaration of foo namespace and foo::X class
namespace foo
{
class X;
}
//global << overload declaration
ostream& operator<<( ostream& os, const foo::X& x );
namespace foo {
class X {
public:
X( int i ) : m_i( i ) { }
//make global overload a friend - notice the ::
friend ostream& ::operator<<( ostream& os, const X& x );
private:
int m_i;
};
}
//actual definition of the global function
ostream& operator<<( ostream& os, const foo::X& x )
{
os << x.m_i;
return os;
}
int main()
{
foo::X x( 7 );
cerr << x << endl;
return 0;
}
also, under convention, should operator<<() live in foo or should it be global space
However I think that you should see that friend operator as a member of A, so it should be in namespace foo.
Or you could avoid the friend (providing a A::print method), and put it in the global.
only says that said function is considered a friend of Foo (if put inside Foo). It does not actually declare the function. Hence why you need the actual declaration.
thx guestgulkan, hamsterman, ne555, jsmith for your additional comments
I've been googling around for answers on the proper scope for operator<<() and haven't found any satisfactory answers yet - some people have actually tried to make it part of std!
On one hand, I think that it should be in global namespace (or std) since operator<<() for ostreams should have consistent semantics from the highest levels.
On the other hand, I've seen comments that we shouldn't pollute the global namespace; though I'd be very afraid of code which subverts the meaning of operator<<() for ostreams for some particular, non-standard usage.
I wonder if the designers of iostream have implied any preferences for users...
I think you are worrying too much.
AFAICS you aren't polluting it because your class is in a namespace. The only problem could be that another provider uses the same name for its namespace and the same name for the class. ::operator<<(std::cout, foo::A()); defeats the purpose of operator overloading, so it does not matter where it is located as long as there is only one.
You could also consider
The same could be say of the operators < > <= >=, == != or + * / -
while < could be a method or be defined in the foo namespace, > <= >= will be in std::rel_ops