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&>*)' ```