On 28.01.2014 21:47, Peter wrote:
> Consider this definition (namespace and class share the same name):
>
> namespace Foo
> {
> int x;
>
> class Foo
> {
> public:
> static int x;
> };
>
> int Foo::x;
> }
>
> I wondered what Foo::x would refer to with "using" directive used for namespace Foo: a global variable x in namespace Foo or static member of class Foo? Basically, I assumed the following code would not compile:
>
> int main()
> {
> using namespace Foo;
> Foo::x;
> return 0;
> }
>
> My reasoning went like this:
>
> - Foo::x is a global variable x from namespace Foo
> - Foo::Foo::x is a static member of class Foo from namespace Foo, but since
> "using" directive is applied, the namespace name can be omitted, thus Foo::x is also a static member of class Foo
> - conclusion: call to Foo::x in main() is ambiguous - it refers to two different entities
I think that is correct.
And I think probably C++11 §7.3.4/6, in the "Using directive" section,
applies:
"If name lookup finds a declaration for a name in two different
namespaces, and the declarations do not declare the same entity and do
not declare functions, the use of the name is ill-formed."
As it happens Visual C++ 12.0 appears to also think so:
[error]
original.cpp(19) : error C2872: 'Foo' : ambiguous symbol
could be 'Foo'
or 'original.cpp(8) : Foo::Foo'
[/error]
> However, the compiler I tested it with (one of g++ recent versions) had
> no trouble disambiguating this: experiments showed Foo::x in main() is
> interpreted as global variable x in namespace Foo. Moreover, if I remove
> the definition of global x from namespace Foo, then the compiler emits
> the following error:
>
> main.cpp: In function 'int main()':
> main.cpp:16:4: error: 'x' is not a member of 'Foo'
> Foo::x;
>
> so it doesn't find the static member of class Foo.
Except that I believe that's wrong, it's reasonable: maybe its how the
language should be.
> In order for the compiler to find it I have to qualify it fully as
> Foo::Foo::x despite the "using namespace Foo;" line.
That's not full qualification, and Visual C++ still emits the diagnostic
above.
Full qualification is
::Foo::Foo::x;
and this is accepted by Visual C++.
> Why?
I think the ambiguity is real and that the g++ failure to diagnose it is
a compiler bug. I could be wrong. But, since the two compilers disagree,
at least one of Visual C++ and g++ has a bug here. ;-)
> How does the lookup work here?
C++11 §7.3.4/2
"A using-directive specifies that the names in the nominated namespace
can be used in the scope in which the using-directive appears after the
using-directive. During unqualified name lookup (3.4.1), the names
appear as if they were declared in the nearest enclosing namespace which
contains both the using-directive and the nominated namespace"
Cheers & hth.,
- Alf