mercredi 1 juillet 2015

Different overloads with std::function parameters and bind causes ambiguity (sometimes)

I have two overloads of a function foo which take different std::functions which results in an ambiguity issue for the latter when used with the result of a std::bind

void foo(std::function<void(int)>) {}
void foo(std::function<int()>) {}

And a couple of functions that match:

void take_int(int) { }
int ret_int() { return 0; }

When using int() with a bind function I get an ambiguity error

foo(std::bind(ret_int)); // ERROR

With the gcc-5.1 error (and similar with clang)

error: call to 'foo' is ambiguous
  foo(std::bind(ret_int));
  ^~~
note: candidate function
void foo(std::function<void(int)>) {}
     ^
note: candidate function
void foo(std::function<int()>) {}

However all of the following work

foo(std::bind(take_int, _1));
foo(take_int);

foo(ret_int);
foo([](){ return ret_int(); });

struct TakeInt {
  void operator()(int) const { }
};

struct RetInt {
  int operator()() const { return 0; }
};

foo(TakeInt{});
foo(RetInt{});

Looking at the std::function constructor

template< class F > 
function( F f );

it would make sense to me that any function with multiple overloads on different std::function types should have ambiguities, but it's only an issue with the call to bind. I then thought "maybe there's some magic happening to handle function types and lambdas and it doesn't deal with actual classes, but it handles those too.

Aucun commentaire:

Enregistrer un commentaire