微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 C++20 using-enum-declaration 进行二义性名称查找

如何解决使用 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 elaborated-enum-specifier ;

[basic.lookup.elab]中定义了这样的查找:

如果 elaborated-type-specifier 中的 class-keyenum 关键字后跟一个 标识符后面没有 ::标识符的查找是仅限类型的([basic.lookup.general])。

elaborated-enum-specifier 是一种 elaborated-type-specifier,所以我们只做类型查找。其定义为,在 [basic.lookup.general]/4:

但是,如果查找是仅类型,则仅考虑类型和模板的特化为类型的声明;此外,如果找到了 typedef-name 及其引用的类型的声明,则丢弃 typedef-name 的声明而不是类型声明。

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

,

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。