The reason that you can call fun is that the friend declaration inside class A makes it visible via argument dependent lookup only. Otherwise friend declarations don't make the functions that they declare automatically visible outside of the class scope where the appear.
You need to add a declaration at namespace scope or inside main to make fun2 visible in main.
E.g.
void fun2();
fun3 is visible inside main because its definition (outside of the class) is also a declaration that makes it visible from main.
ISO/IEC 14882:2011 7.3.1.2:
The name of the friend is not found by unqualified lookup (3.4.1) or by qualified lookup (3.4.3) until a matching declaration is provided in that namespace scope (either before or after the class definition granting friendship).
3.4.2 (Argument-dependent name lookup) / 4:
Any namespace-scope friend functions or friend function templates declared in associated classes are visible within their respective namespaces even if they are not visible during an ordinary lookup (11.3).
answered 2011-10-16T17:13:31.447