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

ambiguous, c++, g++, gcc

Solution

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.

Problem

I'm getting the following compile error in one of my classes, using gcc 3.4.5 (mingw): ``` src/ModelTester/CModelTesterGui.cpp:1308: error: request for member `addListener' is ambiguous include/utility/ISource.h:26: error: candidates are: void utility::ISource<T>::addListener(utility::IListener<T>*) [with T = const SConsolePacket&] include/utility/ISource.h:26: error: void utility::ISource<T>::addListener(utility::IListener<T>*) [with T = const SControlPacket&] ``` Hopefully you can see that `ISource<T>` is a template interface that just indicates that the object can be an informer for an object that is of some matching type `IListener<T>`. So the thing that has me irked is this idea that for some reason functions are ambiguous when, as far as I can tell, they are not. The `addListener()` method is overloaded for different input types `IListener<const SConsolePacket&>` and `IListener<const SControlPacket&>`. The usage is: ``` m_controller->addListener( m_model ); ``` Where `m_model` is a pointer to an `IRigidBody` object, and `IRigidBody` inherits only from `IListener< const SControlPacket& >` and definately not from `IListener< const SConsolePacket& >` As a sanity check, I used doxygen to generate the class hierarchy diagram and doxygen agrees with me that `IRigidBody` does not derive from `IListener< const SConsolePacket& >` Evidently my understanding of inheritence in c++ is not exactly correct. I'm under the impression that `IListener<const SControlPacket&>` and `IListener<const SConsolePacket&>` are two different types, and that the function declarations ``` addListener(IListener<const SConsolePacket&>* listener) ``` and ``` addListener(IListener<const SControlPacket&>* listener) ``` declare two separate functions that do two separate things depending on the (distinct) different type of the parameter that is input. Furthermore, I'm under the impression that a pointer to an `IRigidBody` is also a pointer to an `IListener<const SControlPacket&>` and that by calling `addListener( m_model )` the compiler should understand that I'm calling the second of the above two functions. I even tried casting `m_model` like this: ``` m_controller->addListener( static_cast<IListener<const SControlPacket&>*>(m_model) ); ``` but still get that error. I cannot for the life of me see how these functions are ambiguous. Can anyone shed light on this issue? P.S. I know how to force the function to be un-ambiguous by doing this: ``` m_controller->ISource<const SControlPacket&>::addListener( m_model ); ``` I just happen to think that is terribly unreadible and I would prefer not to have to do that. Edit... just kidding. That apparently doesn't fix the problem as it leads to a linker error: ``` CModelTesterGui.cpp:1312: undefined reference to `utility::ISource<aerobat::SControlPacket const&>::addListener(utility::IListener<SControlPacket const&>*)' ```

Original source