Ambiguous multiple inheritance of template classes

若如初见. 提交于 2021-02-08 12:32:14

问题


I've got a real situation which can be summarized in the following example:

template< typename ListenerType >
struct Notifier
{
    void add_listener( ListenerType& ){}
};

struct TimeListener{ };
struct SpaceListener{ };

struct A : public Notifier< TimeListener >
         , public Notifier< SpaceListener >
{

};

struct B : TimeListener{ };

int main()
{
    A a;
    B b;

    a.add_listener( b );    // why is ambiguous?

    return 0;
}

Why is not obvious to the compiler that B is a TimeListener, and therefore the only possible overload resolution is Notifier< TimeListener >::add_listener( TimeListener& ) ?


回答1:


The lookup rules for member names say that your code is ambiguous, because the name is found in two base classes and therefore the lookup set is invalid. You don't need to be familiar with all the details of lookup sets and merging; the important detail is that both base classes are checked and the name add_listener is found in both, which creates an ambiguity.

The easy fix is to bring those base class names into A with using-declarations. This means that both versions of add_listener are looked up in A, rather than in the base classes, so there is no merge ambiguity:

struct A : public Notifier< TimeListener >
         , public Notifier< SpaceListener >
{
    using Notifier<TimeListener>::add_listener;
    using Notifier<SpaceListener>::add_listener;
   //plus any more base classes
};

Live Demo




回答2:


The standard indicated compiler isn't smart enough to resolve the symbol -- it's defined as an ambiguous operation despite the fact you could logically work it out in this instance. Your compiler is probably only looking for symbol names and not for prototypes after it finds both possible symbols.

You can tell the compiler that you accept both types explicitly by disambiguating the template symbols that you know should be accepted. This will get the compiler to accept either form and then apply the template. Below is an example of this. I can't test this at my computer currently but it should work if the compiler is having difficulty resolving the symbols in your original example:

struct A : public Notifier< TimeListener >
         , public Notifier< SpaceListener >
{
   using Notifier< TimeListener >::add_listener;
   using Notifier< SpaceListener >::add_listener;
};


来源:https://stackoverflow.com/questions/35874029/ambiguous-multiple-inheritance-of-template-classes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!