使用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 Anamespace A,因为我们的查找是仅类型的,所以我们只考虑前者而不考虑后者。结果,我们只有一个候选人,而这就是我们的查找找到的候选人。没有歧义。


回答

MSVC 在这里是正确的。第一种情况是仅类型查找(因为它被视为详细的类型说明符),因此它会忽略命名空间并通过using-directive查找枚举。在第二种情况下,以下内容::允许找到命名空间,因此不明确。


以上是使用C++20using-enum-declaration进行二义性名称查找的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>