How does the name lookup work in this case?


P

Peter

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

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 followingerror:

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. In order for the compiler to find it I have to qualify it fully as Foo::Foo::x despite the "using namespace Foo;" line. Why? How does the lookup work here?
 
Ad

Advertisements

A

Alf P. Steinbach

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++.


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
 
P

Peter

In order for the compiler to find it I have to qualify it fully as
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++.

Perhaps a silly question, but what's the difference
between ::Foo::Foo::x and Foo::Foo::x here?
I thought they were equal in this context.
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. ;-)

I also think this may be a g++ bug (unless there's yet another
obscure C++ rule according to which the compiler isn't supposed to
interpret Foo::x as static member of class Foo in this case).
 
Ö

Öö Tiib

On Thursday, 30 January 2014 20:09:52 UTC+2, Peter wrote:

Attribute quotes, please.
Perhaps a silly question, but what's the difference
between ::Foo::Foo::x and Foo::Foo::x here?
I thought they were equal in this context.

The difference is what Alf said, one is fully qualified name
and other is not. Other 'x' in context of your question is
'::Foo::x' when fully qualified.
 
Ad

Advertisements

Ö

Öö Tiib

Getting back to the main point of the thread...
as Alf pointed out, since g++ and Visual C++
respond to my code differently, then at least
one of them handles it wrong. Any opinions
on which (if any) is correct?

My opinion is that usage of unqualified name 'Foo' after doing
'using namespace Foo;' that contains other 'Foo' is ambiguous.
So even when one of the '::Foo::Foo::x' or '::Foo::x' is not
available it should not compile. I'm not sure how gcc looks it
up. Perhaps it tries to be overly smart somewhere.

I tried with clang, it did also reject the code.
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top