c++11 - Resolving ambiguous overload on function pointer and std::function for a lambda using + -
in following code, first call foo ambiguous, , therefore fails compile.
the second, added + before lambda, resolves function pointer overload.
#include <functional> void foo(std::function<void()> f) { f(); } void foo(void (*f)()) { f(); } int main () { foo( [](){} ); // ambiguous foo( +[](){} ); // not ambiguous (calls function pointer overload) } what + notation doing here?
the + in expression +[](){} unary + operator. defined follows in [expr.unary.op]/7:
the operand of unary
+operator shall have arithmetic, unscoped enumeration, or pointer type , result value of argument.
the lambda not of arithmetic type etc., can converted:
[expr.prim.lambda]/3
the type of lambda-expression [...] unique, unnamed non-union class type — called closure type — properties described below.
[expr.prim.lambda]/6
the closure type lambda-expression no lambda-capture has
publicnon-virtualnon-explicitconstconversion function pointer function having same parameter , return types closure type's function call operator. value returned conversion function shall address of function that, when invoked, has same effect invoking closure type’s function call operator.
therefore, unary + forces conversion function pointer type, lambda void (*)(). therefore, type of expression +[](){} function pointer type void (*)().
the second overload void foo(void (*f)()) becomes exact match in ranking overload resolution , therefore chosen unambiguously (as first overload not exact match).
the lambda [](){} can converted std::function<void()> via non-explicit template ctor of std::function, takes type fulfils callable , copyconstructible requirements.
the lambda can converted void (*)() via conversion function of closure type (see above).
both user-defined conversion sequences, , of same rank. that's why overload resolution fails in first example due ambiguity.
according cassio neri, backed argument daniel krügler, unary + trick should specified behaviour, i.e. can rely on (see discussion in comments).
still, i'd recommend using explicit cast function pointer type if want avoid ambiguity: don't need ask on , why works ;)
Comments
Post a Comment