1

why this works

struct Base {
    virtual void visit(const A &) { };
    virtual void visit(const B &) { };
}

and this complains about ambiguity when calling visit method

template< typename T >
struct X {
    virtual void visit(const T &) { };
};

struct Base: X< A >, X< B > { };

this also shows the same problem:

struct Y {
   virtual void visit(const A &) { };
};

struct Z {
    virtual void visit(const B &) { };
};

struct Base: Z, Y { };

somehow it looks like the multiple inheritance messes with the virtual function signatures...

with gcc version 4.8.0 20130411 (prerelease)

curiousguy
  • 8,038
  • 2
  • 40
  • 58
  • possible duplicate of [multiple-inheritance-template-class](http://stackoverflow.com/questions/3360892/multiple-inheritance-template-class) – yngccc May 09 '13 at 01:02
  • Side note: You do not need `;` after a `}` ending a function body as in `virtual void visit(const A &) { };` and this is ugly. – curiousguy May 14 '13 at 05:07

1 Answers1

0

Here virtual-ness is irrelevant and the fact 2 base classes are template classes is irrelevant. A simpler code with the same issue is:

struct A {
   void f(const A &) { }
};

struct B {
    void f(const B &) { }
};

struct Der: A,B { };

Here Der has two inherited members: A::f(const A &) and B::f(const B &); they can be invoked this way:

Der d;
d.A::f(d);
d.B::f(d);

but not this way:

d.f((A&)d); // error: ambiguous name lookup
d.f((B&)d); // error: ambiguous name lookup

Member function overloading resolution does not work the way you think (find both f then keep the one which has a compatible argument list).

In C++, member name-lookup finds all non-hidden member declarations with a given name, so here it finds A::f(const A &) and B::f(const B &), then it fails immediately if these members are not declared in the same class.

You can solve this problem by adding 2 declarations in the same class:

struct Der: A,B {
    using A::f; // imports A::f(const A &)
    using B::f; // imports B::f(const B &)
};

Then you can do:

Der d;
d.f((A&)d); // OK: Der::f(&A)

Remember: this is purely a member name-lookup ambiguity.

curiousguy
  • 8,038
  • 2
  • 40
  • 58