Friends are very, very weird.
Code:
namespace ns {
class X { friend void fn(X&); };
}
This interesting snippet has the following effects:
1) Declare and define a namespace 'ns'.
2) Declare and define a class 'ns::X'.
3) Declare a function 'ns::fn(ns::X&)' that is a friend of 'ns::X'. However, the declaration is special in that the compiler doesn't find it with normal name lookup, i.e. if the compiler works correctly, this should fail to compile:
Code:
int main()
{
ns::X x;
ns::fn(x); // error: ns::fn not found
}
However, the function can be found via argument-dependent lookup:
Code:
int main()
{
ns::X x;
fn(x); // works
}
This is the case for names (functions and classes) that are unknown prior to the friend declaration.
Now consider this case:
Code:
class A;
namespace ns {
class B;
class X {
class D;
friend class A; // references ::A
friend class B; // references ns::B
friend class C; // hidden-declares and references ns::C
friend class D; // references ns::X::D
};
class C {}; // defines ns::C, which is a friend of ns::X
class A {}; // declares and defines ns::A, which has no relation to ns::X
}
class A {}; // defines ::A, which is a friend of ns::X
class C {}; // declares and defines ::C, which has no relation to ns::X