使用C++20using-enum-declaration进行二义性名称查找
考虑使用 C++20 using-enum-declaration 的以下代码片段:
namespace A { enum A {}; };
using namespace A;
using enum A;
gcc-trunk拒绝它:
<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拒绝它:
<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详细枚举说明符;
在[basic.lookup.elab] 中定义了这样的查找:
如果详细类型说明符中的类键或
enum关键字后跟一个标识符,而后跟不跟 ? ?,标识符的查找是仅限类型的([basic.lookup.general])。::
一个阐述,枚举符是一种阐述类型说明符,所以我们做的类型只查找。在[basic.lookup.general]/4 中定义为:
但是,如果查找是type-only,则只考虑其特化为类型的类型和模板的声明;此外,如果找到typedef-name及其引用的类型的声明,则丢弃 typedef-name 的声明而不是类型声明。
这意味着当我们查找 时A,我们同时找到了enum A和namespace A,因为我们的查找是仅类型的,所以我们只考虑前者而不考虑后者。结果,我们只有一个候选人,而这就是我们的查找找到的候选人。没有歧义。
回答
MSVC 在这里是正确的。第一种情况是仅类型查找(因为它被视为详细的类型说明符),因此它会忽略命名空间并通过using-directive查找枚举。在第二种情况下,以下内容::允许找到命名空间,因此不明确。
THE END
二维码