The following code which doesn\'t compile under clang but does under gcc and VS:
template class bar;
namespace NS
{
template
From cppreference:
Names introduced by friend declarations within a non-local class X become members of the innermost enclosing namespace of X, but they do not become visible to lookup (neither unqualified nor qualified) unless a matching declaration is provided at namespace scope, either before or after the class definition. Such name may be found through ADL which considers both namespaces and classes. Only the innermost enclosing namespace is considered by such friend declaration when deciding whether the name would conflict with a previously declared name.
void h(int); namespace A { class X { friend void f(X); // A::f is a friend class Y { friend void g(); // A::g is a friend friend void h(int); // A::h is a friend, no conflict with ::h }; }; // A::f, A::g and A::h are not visible at namespace scope // even though they are members of the namespace A X x; void g() { // definition of A::g f(x); // A::X::f is found through ADL } void f(X) {} // definition of A::f void h(int) {} // definition of A::h // A::f, A::g and A::h are now visible at namespace scope // and they are also friends of A::X and A::X::Y }
It's not the standard, but it is in general correct. So clang seems to be right.