首页 > 解决方案 > 使用 C++20 using-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'

哪个编译器是对的?

标签: c++language-lawyerc++20name-lookupusing-declaration

解决方案


gcc 在这里是错误的(提交100'084)。

的语法using enum A;来自[enum.udecl]

使用枚举声明

    using 详细枚举说明符 ;

在[basic.lookup.elab]中定义了对此类事物的查找:

如果详细类型说明符中的类键enum关键字后跟一个标识符,而该标识符后面不跟 <code>::​,则对标识符的查找是仅类型的([basic.lookup.general])。

详细枚举说明符是一种详细说明类型说明符,因此我们只进行类型查找。在[basic.lookup.general]/4中定义为:

但是,如果查找是type-only,则只考虑类型和特化为类型的模板的声明;此外,如果找到typedef-name和它所引用的类型的声明,则丢弃 typedef-name 的声明而不是类型声明。

这意味着当我们查找 时A,我们同时找到了enum Anamespace A,因为我们的查找是仅类型的,所以我们只考虑前者而不考虑后者。结果,我们只有一个候选人,这就是我们的查找找到的候选人。没有歧义。


推荐阅读