Request for Member '...' Is Ambiguous in G++

request for member `...' is ambiguous in g++

Looks like your situation is like this:

struct A {
void f();
};

struct B {
void f(int);
};

struct C : A, B { };

int main() {
C c;
c.B::f(1); // not ambiguous
c.f(1); // ambiguous
}

The second call to f is ambiguous, because in looking up the name, it finds functions in two different base class scopes. In this situation, the lookup is ambiguous - they don't overload each other. A fix would be to use a using declaration for each member name. Lookup will find names in the scope of C and don't lookup further:

struct C : A, B { using A::f; using B::f; };

Now, the call would find two functions, do overload resolution, and find that the one taking int will fit. Carried over to your code, it would mean that you have to do something like the following

struct controller : ISource<const SConsolePacket&>, ISource<const SControlPacket&> {
using ISource<const SConsolePacket&>::addListener;
using ISource<const SControlPacket&>::addListener;
};

Now, the two names are in the same scope, and now they can overload each other. Lookup will now stop at the controller class, not diving further into the two base-class branches.

error: request for member is ambiguous c++;

Your compiler can not distinguish between:

NetflixCanada::NetflixUkraine::setBrowser

and

NetflixCanada::NetflixPoland::NetflixUkraine::setBrowser

As mention in the comments, read about "The deadly diamond of death"

C++: request for member is ambiguous

The problem is that you're using pointers. You aren't calling c::operator-> but just dereferencing cMain which is uninitialized and leads to UB. Removing the pointers (for the most part) fixes the problem:

#include <iostream>

class c1{
public:
void f(){std::cout<<"In f1\n";}
};
class c2{
public:
void f(){std::cout<<"In f2\n";}
};

template <typename T>
class c { // No longer derives from c1 and c2
T t; // No longer a pointer
public:
T* operator->() { return &t; }
};

int main()
{
c<c1> cMain; // No longer a pointer
cMain->f(); // Calls c::operator->() now
return 0;
}

see it work

Of course you don't need c to derive from c1 and c2 (or anything) for this to work.

Understanding how to solve ambiguous member requests in c++

First of all, to make it work just do the following changes

class B : virtual public A
...

class C : virtual public A

This problem in multiple inheritance is called the diamond problem. Check out this link to know more
http://www.cprogramming.com/tutorial/virtual_inheritance.html

Ambiguity error accessing equality comparison operator in G++

Indeed the global operator operator==(const C&, const C&) has priority. However the compiler "want to know" all the possibilities in order to decide: In other words: as soon as you try to use the operator== the compiler requires you to have no ambiguities, even if the required alternative is not between the ambiguous one.



struct C : A, B { using A::operator==; }; 

This resolves the ambiguity and allows you to use the global operator==

https://onlinegdb.com/nxMjPN4NC

#include <iostream>

struct A {
bool operator ==(const A&) const { std::cout << "A" << std::endl; return true; };
};

struct B {
bool operator ==(const B&) const { std::cout << "B" << std::endl; return true; };
};

struct C : A, B
{
//using A::operator==; // Uncomment this to make it work.
};

bool operator ==(const C&, const C&) { std::cout << "C" << std::endl; return true; }

int main()
{
C c1, c2;

c1==c2;

return 0;
}

Result (when resolved):

C

Why is this call to member function ambiguous?

Non-static member functions, like the two:

void func(double);    // #1
void func(int) const; // #2

accept also an implicit object parameter which is considered in overload resolution ([over.match]/p1) as any other argument:

Overload resolution is a mechanism for selecting the best function to call given a list of expressions that are to be the arguments of the call and a set of candidate functions that can be called based on the context of the call. The selection criteria for the best function are the number of arguments, how well the arguments match the parameter-type-list of the candidate function, how well (for non-static member functions) the object matches the implicit object parameter, and certain other properties of the candidate function.

After incorporating the implicit object parameter into the member functions signatures, the compiler sees two overloads:

void func(Base&, double);    // #1
void func(const Base&, int); // #2

and tries to select the best viable function based on the call:

Base base;
base.func(1);

The conversion from base (which is a non-const lvalue of type Base) to Base& has an Exact Match rank (direct reference binding yields an Identity conversion) -- see Table 13. The conversion from base to const Base& is also of an Exact Match rank, however, [over.ics.rank]/p3.2.6 declares #1 to have a better conversion sequence:

— S1 and S2 are reference bindings ([dcl.init.ref]), and the types to which the references refer are the same type except for top-level cv-qualifiers, and the type to which the reference initialized by S2 refers is more cv-qualified than the type to which the reference initialized by S1 refers. [ Example:

int f(const int &);
int f(int &);
int g(const int &);
int g(int);

int i;
int j = f(i); // calls f(int &)
int k = g(i); // ambiguous

Now for the second parameter, a conversion from an integral prvalue 1 to double is a Floating-integral conversion ([conv.fpint]) which is given a Conversion rank. On the other hand, 1 to int is an Identity conversion which is of an Exact Match rank. For this argument, #2 is considered to have a better conversion sequence ([over.ics.rank]/p3.2.2):

— the rank of S1 is better than the rank of S2, or S1 and S2 have the same rank and are distinguishable by the rules in the paragraph below, or, if not that, [...]

Overload resolution to succeed requires that there exists at most one parameter for which conversion sequences differ ([over.match.best]):

Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then

— for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2), or, if not that, [...]

Here, ICS0(#1) is better than ICS0(#2), but in turn, ICS1(#2) is better than ICS1(#1), so the compiler can't choose between the two overloads and detects ambiguity.

error: request for member '..' in '..' which is of non-class type

Foo foo2();

change to

Foo foo2;

You get the error because compiler thinks of

Foo foo2()

as of function declaration with name 'foo2' and the return type 'Foo'.

But in that case If we change to Foo foo2 , the compiler might show the error " call of overloaded ‘Foo()’ is ambiguous".

Ambiguous call when inheriting multiple times from generic base class

This code is ill-formed. If the operator() is not available in the derived class, then name lookup only considers the base class if there is exactly one base class. If there are multiple base classes, then none of the base classes are considered in name lookup.

As you've mentioned, you can copy the implementations of operator() into the derived class, and that works, but you can also bring both of the operator() names into the derived class with a using directive, like this:

class : public Translate<T1>, public Translate<T2> {
public:
using Translate<T1>::operator();
using Translate<T2>::operator();
} tr;

Here's a demo.

Overloaded lambdas in C++ and differences between clang and gcc

Looks like a Clang bug to me.

The general rule is that member functions of the same name in different base classes do not overload. For example:

struct Foo { void bar(); };
struct Baz { void bar(int); };
struct Quux : Foo, Baz { };

int main() { Quux().bar(); } // error on both GCC and Clang

For whatever reason, Clang fails to diagnose this ambiguity for operator().

A using-declaration lifts the named base class members to the derived class scope, allowing them to overload. Hence:

struct Quux_2 : Foo, Baz { using Foo::bar; using Baz::bar; };
Quux_2().bar(); // OK.

In the working version of the code, the using declarations recursively bring every operator() declaration in the template arguments into the scope of the most derived class, allowing them to overload.



Related Topics



Leave a reply



Submit