Func f1 = []() {};
is copy initialization, which requires two user-defined implicit conversion to construct f1
, the 1st one is from the lambda to the function pointer, the 2nd one is from the function pointer to Func
. Only one user-defined implicit conversion is allowed in one conversion sequence so it fails.
(emphasis mine)
If T is a class type, and the cv-unqualified version of the type of other is not T or derived from T, or if T is non-class type, but the type of other is a class type, user-defined conversion sequences that can convert from the type of other to T (or to a type derived from T if T is a class type and a conversion function is available) are examined and the best one is selected through overload resolution.
and
Implicit conversion sequence consists of the following, in this order:
1) zero or one standard conversion sequence;
2) zero or one user-defined conversion;
3) zero or one standard conversion sequence.
For f2 = []() {};
the appropriate assignment operator is tried to be called, Func
has one and it expects the function pointer as the argument; only one implicit conversion from the lambda to function pointer is required and then it works well.
Func f3([]() {});
is direct initialization, the appropriate constructor is tried to be called, Func
has one and it expects the function pointer as the argument. Then it's the same as f2
.
You may get the point from the difference between copy initialization and direct initialization.
In addition, the implicit conversion in copy-initialization must produce T directly from the initializer, while, e.g. direct-initialization expects an implicit conversion from the initializer to an argument of T's constructor.