It is legal in C++ to declare nested anonymous namespaces in the following manner:
namespace {
namespace {
struct Foo
{
};
}
}
namespace {
struct Foo // SAME IDENTIFIER AS <unnamed>::<unnamed>::Foo!!!
{
};
}
However, how would you declare an identifier using an explicitly typed Foo to avoid ambiguity?
EDITED -- for all of you who do not read the question.
p.s. I have no intentions to use this sort of constructs, but I need to understand whether it is possible to disambiguate Foo in case someone finds a legitimate use for it. My compiler extension needs to handle all cases.
The C++ standard states it pretty clearly in 7.3.1.1p1:
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.
So from above, we know that your code actually translates to 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 I was wrong. Corrected by comments below.Foo
can only be accessed within namespace unique1
and the second Foo
can be accessed in the global namespace due to using namespace unique3;
.
Then from 7.3.4p4:
For unqualified lookup (3.4.1), the using-directive is transitive: if a scope contains a using-directive that nominates a second namespace that itself contains using-directives, the effect is as if the using-directives from the second namespace also appeared in the first.
Therefore, when you refer to Foo
, it can mean either unique1::unique2::Foo
or unique3::Foo
, which is an error. Note that the other answer says: has hidden unique name that cannot be accessed
. This is incorrect, they can be accessed due to the using directives, it is just that both names are visible.
However, by prepending the scope resolution operator ::
to Foo
you can access unique3::Foo
because of the following:
From 3.4.3.2p2:
For a namespace X and name m, the namespace-qualified lookup set S(X,m) is defined as follows: Let S0(X,m) be the set of all declarations of m in X and the inline namespace set of X (7.3.1). If S0(X,m) is not empty, S(X,m) is S0(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.
The emphasized part says using-directives in X
, which in your case means using namespace unique1;
and using namespace unique3;
, so the namespace-qualified lookup set looks like this: S(unique3::Foo)
, which means unique1::unique2::Foo
is not included in the set and therefore is not an error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With