Please consider the following code:
struct A
{
void f()
{
}
};
struct B1 : A
{
};
struct B2 : A
{
};
struct C : B1, B2
{
void f() // works
{
B1::f();
}
//using B1::f; // does not work
//using B1::A::f; // does not work as well
};
int main()
{
C c;
c.f();
return 0;
}
I kindly ask you not to copy paste a standard reply on how to solve the diamond problem ("use virtual inheritance"). What I am asking here is why doesn't a using-declaration work in this case. The exact compiler error is:
In function 'int main()':
prog.cpp:31:6: error: 'A' is an ambiguous base of 'C'
c.f();
I got the impression a using-declaration should work from this example:
struct A
{
void f()
{
}
};
struct B
{
void f()
{
}
};
struct C : A, B
{
using A::f;
};
int main()
{
C c;
c.f(); // will call A::f
return 0;
}
Someone else can find the standard quote but I'm going to explain conceptually.
It doesn't work because a using-declaration only affects name lookup.
Your using-declaration causes name lookup to succeed where it would otherwise fail, that is, it tells the compiler where to find the function f
. But it does not tell it which A
subobject f
acts on, that is, which one will be passed as the implicit this
parameter when f
is called.
There is only a single function A::f
even though there are two A
subobjects of C
, and it takes an implicit this
argument of type A*
. In order to call it on a C
object, C*
must be implicitly converted to A*
. This is always ambiguous, and is not affected by any using-declarations.
(This makes more sense if you put data members inside A
. Then C
would have two of each such data member. When f
is called, if it accesses data members, does it access the ones in the A
subobject inherited from B1
, or the ones in the A
subobject inherited from B2
?)