c++ - Different overloads with std::function parameters is ambiguous with bind (sometimes) -
i have 2 overloads of function foo
take different std::function
s results in ambiguity issue latter when used result of std::bind
. don't understand why only ambiguous.
void foo(std::function<void(int)>) {} void foo(std::function<int()>) {} void take_int(int) { } int ret_int() { return 0; }
when using int()
bind
function ambiguity error
foo(std::bind(ret_int)); // error
with gcc-5.1 error (and similar clang)
error: call 'foo' ambiguous foo(std::bind(ret_int)); ^~~ note: candidate function void foo(std::function<void(int)>) {} ^ note: candidate function void foo(std::function<int()>) {}
however of 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 @ std::function
constructor
template< class f > function( f f );
it make sense me function multiple overloads on different std::function
types should have ambiguities, it's issue call bind. thought "maybe there's magic happening handle function types , lambdas , doesn't deal actual classes," handles too.
there's note on en.cppreference says [since c++14]
this constructor not participate in overload resolution unless f callable argument types args... , return type r
the problem exists in how bind allowed called. cppreference states
if of arguments supplied in call g() not matched placeholders stored in g, unused arguments evaluated , discarded.
in other words, need pass at least many arguments underlying functor expects.
this means following valid
int f(); auto b = std::bind(f); b(1, 2, 3); // arguments aren't used
so saying
auto b = std::bind(ret_int) b(1);
works, 1
discarded, therefore following valid, , overload selection becomes ambiguous
std::function<void(int)> f = std::bind(ret_int);
the inverse not true, however
std::function<int()> f = std::bind(take_int);
because take_int
cannot called no arguments.
takeaway: lambda > bind
this specific case seems broken under c++14 though
n4140 20.9.11.2.1/8
template<class f> function(f f);
remarks: these constructors shall not participate in overload resolution unless f callable argument types argtypes... , return type r
because ret_int
not return void
when called no arguments.
Comments
Post a Comment