使用枚举声明的 C++20 模糊名称查找
Ambiguous name lookup with C++20 using-enum-declaration
考虑使用 C++20 using-enum-declaration 的以下代码片段:
namespace A { enum A {}; };
using namespace A;
using enum A;
gcc-trunk rejects 它与:
<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;
| ^
但是,msvc 接受它。有趣的是,如果我为 enum A
:
添加命名空间限定符
namespace A { enum A {}; };
using namespace A;
using enum A::A;
gcc 这次接受 它,但是 msvc rejects 它与:
<source>(4): error C2872: 'A': ambiguous symbol
<source>(1): note: could be 'A'
<source>(1): note: or 'A::A'
哪个编译器是正确的?
这里gcc错了(已提交100'084)。
using enum A;
的语法来自 [enum.udecl]:
using-enum-declaration:
using
elaborated-enum-specifier ;
中定义了此类内容的查找
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]).
一个 elaborated-enum-specifier 是一种 elaborated-type-specifier,所以我们只进行类型查找。定义为 [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.
这意味着当我们查找 A
时,我们同时找到 enum A
和 namespace A
,因为我们的查找是仅类型的,我们只考虑前者而不是前者后者。结果,我们只有一个候选者,这就是我们的查找找到的那个。没有歧义。
这里的 MSVC 是正确的。第一种情况是仅类型查找(因为它被认为是详细的类型说明符),因此它忽略命名空间并通过 using-directive 查找枚举。第二种情况,下面的::
允许找到命名空间,所以有歧义。
考虑使用 C++20 using-enum-declaration 的以下代码片段:
namespace A { enum A {}; };
using namespace A;
using enum A;
gcc-trunk rejects 它与:
<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;
| ^
但是,msvc 接受它。有趣的是,如果我为 enum A
:
namespace A { enum A {}; };
using namespace A;
using enum A::A;
gcc 这次接受 它,但是 msvc rejects 它与:
<source>(4): error C2872: 'A': ambiguous symbol
<source>(1): note: could be 'A'
<source>(1): note: or 'A::A'
哪个编译器是正确的?
这里gcc错了(已提交100'084)。
using enum A;
的语法来自 [enum.udecl]:
中定义了此类内容的查找using-enum-declaration:
using
elaborated-enum-specifier;
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]).
一个 elaborated-enum-specifier 是一种 elaborated-type-specifier,所以我们只进行类型查找。定义为 [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.
这意味着当我们查找 A
时,我们同时找到 enum A
和 namespace A
,因为我们的查找是仅类型的,我们只考虑前者而不是前者后者。结果,我们只有一个候选者,这就是我们的查找找到的那个。没有歧义。
这里的 MSVC 是正确的。第一种情况是仅类型查找(因为它被认为是详细的类型说明符),因此它忽略命名空间并通过 using-directive 查找枚举。第二种情况,下面的::
允许找到命名空间,所以有歧义。