Do Derived1::Base and Derived2::Base refer to the same type?

for*_*818 15 c++ multiple-inheritance qualified-name diamond-problem language-lawyer

MSVC, Clang and GCC disagree on this code:

struct Base { int x; };
struct Der1 : public  Base {};
struct Der2 : public  Base {};

struct AllDer : public Der1, public Der2 {
    void foo() {
        Der1::Base::x = 5;
    }
};
Run Code Online (Sandbox Code Playgroud)

Godbolt

GCC:

<source>: In member function 'void AllDer::foo()':    
<source>:10:21: error: 'Base' is an ambiguous base of 'AllDer'    
   10 |         Der1::Base::x = 5;    
      |                     ^    
Compiler returned: 1
Run Code Online (Sandbox Code Playgroud)

Clang gives a similar error, and MSVC gives no error.

Who is right here?

I suppose this is covered in [class.member.lookup], but I have difficulties understanding what it is trying to tell me for this case. Please quote the relevant parts and if possible explain in plain English.

PS: Inspired by this question Why is Reference to Base Class ambiguous with :: -operator trough derived class?

PPS: Actually my doubt is whether Der1::Base refers to the type, that would be Base (and then Der2::Base is exactly the same type), or to the subobject. I am convinced that it is the first, but if it is the latter then MSVC would be right.

MSa*_*ers 6

要回答标题中的问题,是的,Derived1::Base引用了注入的类名[class.pre] BaseDerived2::Base。两者均指类::Base

现在,如果Base有一个静态成员x,那么查找Base::x将是明确的。只有一个。

这个例子中的问题是它x是一个非静态成员,并且AllDer两个这样的成员。您可以x通过指定一个只有一个成员的明确基类来消除这种访问的歧义。是一个明确的基类,它有一个成员,因此明确指定您指的是两个成员中的哪一个。too 只有一个成员,但它不是. 的每个实例都有两个类型为 的子对象。因此,在您的示例中是模棱两可的。由于只是 的另一个名称,因此这仍然不明确。AllDerxDerived1xDerived1::xxAllDerBasexAllDerAllDerBaseBase::xDerived1::BaseBase

[class.member.lookup] 指定x在嵌套名称说明符的上下文中查找,因此必须首先解析。我们确实在寻找Base::x,而不是Derived1::x,因为我们从解析Derived1::Baseas开始Base。这部分成功,只有一个有xBase.注意12 [class.member.lookup]明确地告诉你,当有与多个同名的子对象的利用无歧义的名称查找可能仍会失败。D::i在那个例子中基本上是你的Base::x.


Dan*_*ani 2

之所以可以将类名作为类的成员来引用,是因为cpp为方便使用而给它起了别名,就好像你using Base = ::Base;在Base里面写的一样。
\n您\xe2\x80\x99面临的问题Der1::BaseBase
\n因此,当你写 时Der1::Base::x,它\xe2\x80\x99s 与 相同Base::x

\n