c++ - Different overloads with std::function parameters is ambiguous with bind (sometimes) -


i have 2 overloads of function foo take different std::functions 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

Popular posts from this blog

OpenCV OpenCL: Convert Mat to Bitmap in JNI Layer for Android -

android - org.xmlpull.v1.XmlPullParserException: expected: START_TAG {http://schemas.xmlsoap.org/soap/envelope/}Envelope -

python - How to remove the Xframe Options header in django? -