Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this virtual call ambiguous?

Tags:

c++

c++11

In the below code I can't figure out why the call to "apply" is reported as ambiguous. There is only one acceptable match for the provided parameter (A_applicator::apply). Note I'd much appreciate references to the standard which would help me determine the resolution flow that causes this ambiguity.

struct A { };
struct B { };
struct A_D : public A { };

struct A_applicator {
    virtual void apply( A ) { }
};
struct B_applicator {
    virtual void apply( B ) { }
};
struct dual_applicator : public B_applicator, public A_applicator {
};

int main() {
    dual_applicator app;
    A_D d;
    app.apply(d);
}

(Online Demo)

like image 209
edA-qa mort-ora-y Avatar asked Jun 15 '13 07:06

edA-qa mort-ora-y


People also ask

How do you fix an ambiguous call to overloaded function?

There are two ways to resolve this ambiguity: Typecast char to float. Remove either one of the ambiguity generating functions float or double and add overloaded function with an int type parameter.

Why is C++ saying Cout is ambiguous?

Whenever you see a compiler error that says something is ambiguous it normally means that you have opened some namespaces (ie using namespace std;) and other namespaces and cout is defined in both namespaces. This means it is ambiguous, the compiler does not know which definition you mean.

What is ambiguity in oops?

Ambiguity in inheritance can be defined as when one class is derived for two or more base classes then there are chances that the base classes have functions with the same name. So it will confuse derived class to choose from similar name functions. To solve this ambiguity scope resolution operator is used “::”.


1 Answers

You seem to think that it should not be ambiguity because one of the functions cannot be called, based on the type of the arguments. But that's not how C++ name resolution works.

This is how it works, more or less: the name of the function is resolved into an overload set. And then the argument list is used to choose between the functions in that set.

Your problem is that the first step cannot be done, because the name apply how it is used, can refer to two different overload sets, and the compiler doesn't know which one to use. It didn't even begin to look at the parameters!

The solutions are easy:

A) Say which function you want:

app.A_applicator::apply(d);

B) Use using to build a unified overload set of member functions, so the expected resolution using arguments is used.

struct dual_applicator : public B_applicator, public A_applicator {
    using A_applicator::apply;
    using B_applicator::apply;
};
like image 85
rodrigo Avatar answered Oct 03 '22 08:10

rodrigo