5

Consider following code snippet with C++20 using-enum-declaration:

namespace A { enum A {}; };

using namespace A;
using enum A;

gcc-trunk rejects it with:

<source>:4:12: error: reference to 'A' is ambiguous
    4 | using enum A;
      |            ^
<source>:1:20: note: candidates are: 'enum A::A'
    1 | namespace A { enum A {}; };
      |                    ^
<source>:1:11: note:                 'namespace A { }'
    1 | namespace A { enum A {}; };
      |           ^
<source>:4:12: error: 'A' has not been declared
    4 | using enum A;
      |            ^

However, msvc accepts it. Interestingly, if I add a namespace qualifier for enum A:

namespace A { enum A {}; };

using namespace A;
using enum A::A;

gcc accepts it this time, but msvc rejects it with:

<source>(4): error C2872: 'A': ambiguous symbol
<source>(1): note: could be 'A'
<source>(1): note: or       'A::A'

Which compiler is right?

2 Answers 2

5

gcc is wrong here (submitted 100'084).

The grammar for using enum A; is from [enum.udecl]:

using-enum-declaration:

    using elaborated-enum-specifier ;

Lookup for such a thing is defined in [basic.lookup.elab]:

If the class-key or enum keyword in an elaborated-type-specifier is followed by an identifier that is not followed by ​::​, lookup for the identifier is type-only ([basic.lookup.general]).

An elaborated-enum-specifier is one kind of elaborated-type-specifier, so we do type-only lookup. Which is defined as, in [basic.lookup.general]/4:

However, if a lookup is type-only, only declarations of types and templates whose specializations are types are considered; furthermore, if declarations of a typedef-name and of the type to which it refers are found, the declaration of the typedef-name is discarded instead of the type declaration.

This means that when we look up A, while we find both the enum A and the namespace A, because our lookup is type-only we only consider the former and not the latter. As a result, we only have a single candidate and that's the one our lookup finds. There is no ambiguity.

Sign up to request clarification or add additional context in comments.

Comments

5

MSVC is correct here. The first case is a type-only lookup (as it’s considered an elaborated type specifier), so it ignores the namespace and finds the enumeration via the using-directive. In the second case, the following :: allows namespaces to be found, so it’s ambiguous.

3 Comments

Wait the second case is supposed to be ambiguous? I love this language. I thought it was so "obvious" that MSVC was wrong for the second one that I didn't even write that...
@Barry gcc seems to have this issue a long time ago.
@Barry: You can do qualified lookup into any enumeration. The fact that you can’t possibly find there an entity that would be a valid subject for an elaborated-type-specifier isn’t considered, as per usual.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.