Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is a call to a C++ struct's function ambiguous if there are inherited members with different parameters?

The code is below. I have one single function f(), and one single function f(int) in my class D, so why is that call ambiguous if both functions have different parameters?

struct A {
    void f() {}
};

struct B: virtual A {
    void f(int i) {}
};

struct C: virtual A {
    void f() {}
};

struct D: B, C {

};

int main()
{
    D d;
    d.f(5); //ambiguous
}
like image 332
SGodoy Avatar asked Jun 25 '17 22:06

SGodoy


2 Answers

The problem here is with member name lookup, which occurs before evaluating which functions are viable and applying overload resolution. When name lookup finds names from two or more unrelated base class, this is considered an ambiguous lookup, which is immediately invalid.

For more details, read about unqualified name lookup in class member definitions. (This is not actually the context you have here, but the same rules apply for a member access expression.)

You could work around this by specifying the base class where you want lookup to start, using a qualified-id:

d.B::f(5);

Or, you could make both functions explicitly visible directly in D:

struct D: B, C {
    using B::f;
    using C::f;
};
like image 96
aschepler Avatar answered Oct 31 '22 14:10

aschepler


The call is ambiguous because both bases A and C of struct D have a function called void f(), even if A's f() is hidden. To disambiguate, you should declare f() in D.

struct A {
    void f() {}
};

struct B: virtual A {
    void f(int i) {}   // <  hides A::f(), even if signature is different,
};

struct C: virtual A {
    void f() {}        // <  hides A::f()
};

struct D: B, C {
                       // f(...) functions in both base... which one hides the other?
};
like image 29
Michaël Roy Avatar answered Oct 31 '22 16:10

Michaël Roy