In the C ++ standard, this is pretty clearly stated in 7.3.1.1p1:
A definition without namespace-name behaves as if it were replaced by
inline(opt) namespace unique { } using namespace unique ; namespace unique { namespace-body }
where an inline string appears if and only if it appears in an unnamed-namespace-definition, all occurrences of unique translations are replaced by the same identifier, and this identifier is different from all other identifiers in the entire program.
So, from the above, we know that your code actually translates into the following:
namespace unique1 {} using namespace unique1; namespace unique1 { namespace unique2 {} using namespace unique2; namespace unique2 { struct Foo { }; } } namespace unique3 {} using namespace unique3; namespace unique3 { struct Foo { }; }
Therefore, your first Foo can only be in namespace unique1 , and the second Foo can be obtained in the global namespace due to using namespace unique3; . I was wrong. Corrected by comments below.
Then from 7.3.4p4:
For an unqualified search (3.4.1), the using directive is transitive: if the scope contains a directive that assigns a second namespace that itself contains directive pointers, the effect looks as if directive pointers from the second namespace also appear on the first line.
So when you refer to Foo , this can mean either unique1::unique2::Foo , or unique3::Foo , which is a mistake . Note that another answer says: has hidden unique name that cannot be accessed . This is incorrect , they can be accessed due to the use of directives, it is just that both names are visible.
However , by adding the scope :: operator to Foo , you can access unique3::Foo because of the following:
From 3.4.3.2p2:
For the namespace X and the name m, the search set using the namespace S (X, m) is defined as follows: let S0 (X, m) be the set of all declarations m in X and the built-in namespace X (7.3.1). If S0 (X, m) is not empty, S (X, m) - S0 (X, m); otherwise, S (X, m) is the union of S (Ni, m) for all the Ni namespaces assigned using directives in X and its built-in namespace .
The underlined part says using-directives in X , which in your case means using namespace unique1; and using namespace unique3; , therefore, the search set, taking into account the namespace, is as follows: S(unique3::Foo) , which means unique1::unique2::Foo not included in the set, and therefore is not an error.