Consider a class D
inherited from two classes B
and C
, each of which inherits not-virtually class A
. There is a method f
in A
, and the same named method in B
hiding the method from A
. I would like to call A::f()
from B
-base class of D
object as follows:
struct A { void f() {} };
struct B : A { void f() {} };
struct C : A {};
struct D : B, C {};
int main() { D{}.B::A::f(); }
Unfortunately, it works only in MSVC, while both GCC and Clang produce the error:
error: 'A' is an ambiguous base of 'D'
demo: https://gcc.godbolt.org/z/jY3v876hK
It looks like GCC/Clang accept but completely ignore B::
prefix in B::A::f()
. Are they right in doing so according to the standard?
Are they right in doing so according to the standard?
Yes. The nested name specifier in A::
, B::A
, or D::B::A
all serve the same purpose, to name the class A
.
[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.
The nested name specifier does not name "a path" to the member, it names a base of D
. And to name A
results in ambiguity.