How does the name lookup work in this case?

Discussion in 'C++' started by Peter, Jan 28, 2014.

  1. Peter

    Peter Guest

    Consider this definition (namespace and class share the same name):

    namespace Foo
    int x;

    class Foo
    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;
    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'

    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?
    Peter, Jan 28, 2014
    1. Advertisements

  2. I think that is correct.

    And I think probably C++11 §7.3.4/6, in the "Using directive" section,

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

    original.cpp(19) : error C2872: 'Foo' : ambiguous symbol
    could be 'Foo'
    or 'original.cpp(8) : Foo::Foo'

    Except that I believe that's wrong, it's reasonable: maybe its how the
    language should be.

    That's not full qualification, and Visual C++ still emits the diagnostic

    Full qualification is


    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. ;-)

    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
    Alf P. Steinbach, Jan 28, 2014
    1. Advertisements

  3. Peter

    Peter Guest

    In order for the compiler to find it I have to qualify it fully as
    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 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).
    Peter, Jan 30, 2014
  4. Peter

    Öö Tiib Guest

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

    Attribute quotes, please.
    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.
    Öö Tiib, Jan 31, 2014
  5. Peter

    Peter Guest

    Peter, Jan 31, 2014
  6. Peter

    Öö Tiib Guest

    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.
    Öö Tiib, Jan 31, 2014
    1. 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 (here). After that, you can post your question and our members will help you out.