在歧义情况下使用限定符号进行类成员访问

4
考虑一个结构体B,它派生自两个结构体A<1>A<2>,每个结构体定义了一个名为D的类型,并且还有一个全局的名为D的类型。然后在B对象后面写入.D::,应该选哪个D
template<int N> struct A{ int v = N; using D = A; };
struct B : A<1>, A<2> {};
using D = A<1>;
int main() { return B{}.D::v; }

根据标准:[basic.lookup.classref]

4 If the id-expression in a class member access is a qualified-id of the form

class-name-or-namespace-name::...

the class-name-or-namespace-name following the . or -> operator is first looked up in the class of the object expression ([class.member.lookup]) and the name, if found, is used. Otherwise it is looked up in the context of the entire postfix-expression.

首先,必须查找结构体B中的D,但在那里它是模糊的。事实上,Clang报告了一个错误:

error: member 'D' found in multiple base classes of different types

但是GCC接受了这段代码,示例:https://gcc.godbolt.org/z/74qraoeac

看起来,GCC将标准解释为在BD是有歧义的,让我们看看B之外。哪个编译器在这里是正确的?


2
我个人认为Clang的行为在这里看起来是正确的。你可以尝试对GCC提出一个错误报告,看看他们是否同意。 - Brian Bi
如果使用return B{}.::D::v;,两者都会很满意。我倾向于在原始代码中(在查找有歧义的“D”所在的封闭命名空间之前),使用clang++正确地查找“B”中的“D”。 - Ted Lyngmo
我同意BrianBi的观点。引用的语言说,只有在找不到名称时才在另一个上下文中查找。但是,名称已经被找到了,只是存在歧义。搜索应该在那里停止。 - Remy Lebeau
谢谢,我已经报告了GCC的错误:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102170 - Fedor
1个回答

2

Clang 是正确的,根据最近对该措辞的澄清,现在它说:

如果对于一个嵌套名称限定符的终端名称([expr.prim.id.qual]),并且不是依赖项,没有找到合格的成员名称,则进行未限定的查找。

现在没有问题的“名称,如果找到”的含义,这可能暗示唯一性。


成员限定名称如何成为终端名称? - Language Lawyer
@LanguageLawyer:这里的D为什么不是 D::的终端名称? - Davis Herring
好的,那么当成员限定名称不是终端名称时呢? - Language Lawyer
@LanguageLawyer:它总是某物的终端名称;问题在于是什么。 - Davis Herring
好的,我明白了。谢谢。 - Language Lawyer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接