Beakie
Beakie

Reputation: 1999

"Ambiguous call to overloaded function"

I have a structure like this, with struct Baz inheriting from 2 different structs, Foo and Bar.

I have 2 methods called the same thing, one with a parameter of Foo and one with a parameter of Baz.

struct Foo
{
};

struct Bar
{
};

struct Baz : Foo, Bar
{
    virtual void something(const Foo& foo)
    {
    };

    virtual void something(const Bar& bar)
    {
    };
};

I call it like this

Baz baz;
baz.something(baz);

And understandably I have an issue with my code knowing which function I am calling if I pass it an instance of Baz. I get “Ambiguous call to overloaded function”.

I know I can cast my Baz to Foo or Bar to resolve the issue...

Baz baz;
baz.something((Bar)baz);

...but is there another way of dealing with this design issue?

I want to call the Foo method ONLY if the object being passed is not of type Bar.

edit:

If this was C# (which it isn't) I could probably solve this using a template where clause.

Upvotes: 1

Views: 995

Answers (1)

First off, note that the cast you've used would create a temporary object. You probably meant this:

baz.something(static_cast<Bar&>(baz));

And to answer your question, it should be possible to use SFINAE for this:

struct Baz : Foo, Bar
{
  virtual void something(const Bar &bar)
  { /* ... */ }

  template <
    class T,
    class = typename std::enable_if<
      std::is_convertible<const T&, const Foo&>::value &&
      !std::is_convertible<const T&, const Bar&>::value
    >::type
  >
  void something (const T &foo)
  { something_impl(static_cast<const Foo&>(foo)); }

private:
  virtual void something_impl(const Foo &foo)
  { /* ... */ }
};

Live example

Upvotes: 2

Related Questions