The behavior of unnamed namespaces is specified in §7.3.1.1 [namespace.unnamed]/p1:
An unnamed-namespace-definition behaves as if it were replaced by
inline_opt namespace unique { /* empty body */ }
using namespace unique ;
namespace unique { namespace-body }
where inline
appears if and only if it appears in the
unnamed-namespace-definition, all occurrences of unique
in a translation unit are replaced by the same identifier, and this
identifier differs from all other identifiers in the entire program.
In particular, note that the declarations inside the unnamed namespace is made visible in the surrounding scope via a using-directive using namespace unique;
.
In Snippet A, foo
is unqualified, so the compiler performs unqualified name lookup (§3.4.1 [basic.lookup.unqual]). Relevant here is paragraph 2 of the subclause:
2 The declarations from the namespace nominated by a using-directive
become visible in a namespace enclosing the using-directive; see
7.3.4. For the purpose of the unqualified name lookup rules described in 3.4.1, the declarations from the namespace nominated by the
using-directive are considered members of that enclosing namespace.
Hence, unqualified name lookup finds both declarations of foo
, and the name is ambiguous.
In Snippet B, A::foo
is qualified, so qualified name lookup rules apply. Since A
is a namespace, the applicable subclause is §3.4.3.2 [namespace.qual]. As relevant here, the rule is specified in paragraph 2 of that subclause:
For a namespace X
and name m
, the namespace-qualified lookup set
S(X,m)
is defined as follows: Let S'(X,m)
be the set of all
declarations of m
in X
and the inline namespace set of X
(7.3.1). If S'(X,m)
is not empty, S(X,m)
is S'(X,m)
; otherwise,
S(X,m)
is the union of S(Ni,m)
for all namespaces Ni
nominated
by using-directives in X
and its inline namespace set.
In other words, qualified name lookup considers namespaces nominated by using-directives only if the name is not found in the specified namespace and its inline namespace set. Here, the name foo
is found in namespace A
, so the unnamed namespace nominated by the using-directive is not considered, and there's no ambiguity.
If you write ::foo
instead of foo
in Snippet A, then qualified lookup rules would apply instead, and there would once again be no ambiguity.