如何解决使用 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-key 或 enum
关键字后跟一个 标识符后面没有 ::
,标识符的查找是仅限类型的([basic.lookup.general])。
elaborated-enum-specifier 是一种 elaborated-type-specifier,所以我们只做类型查找。其定义为,在 [basic.lookup.general]/4:
但是,如果查找是仅类型,则仅考虑类型和模板的特化为类型的声明;此外,如果找到了 typedef-name 及其引用的类型的声明,则丢弃 typedef-name 的声明而不是类型声明。
这意味着当我们查找 A
时,虽然我们同时找到了 enum A
和 namespace A
,但由于我们的查找是仅类型的,因此我们只考虑前者而不考虑后者.结果,我们只有一个候选人,而这就是我们的查找找到的候选人。没有歧义。
MSVC 在这里是正确的。第一种情况是仅类型查找(因为它被认为是精心设计的类型说明符),因此它会忽略命名空间并通过 using-directive 查找枚举。在第二种情况下,下面的 ::
允许找到命名空间,所以它是不明确的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。