Why doesn't assignment operator allow for a lambda expression when done in the same line the object is declared?
It seems to be working in MSVC though.
Test the code: https://godbolt.org/g/n2Tih1
class Func { typedef void(*func_type)(); func_type m_f; public: Func() {} Func(func_type f) : m_f(f) {} Func operator=(func_type f) { m_f = f; return *this; } }; int main() { // doesn't compile in GCC and clang, it does in MSVC Func f1 = []() { }; // compiles! Func f2; f2 = []() { }; // compiles! Func f3([]() { }); }
In other words, a good compiler will not create a copy for copy-initialization when it can be avoided; instead it will just call the constructor directly -- ie, just like for direct-initialization.
Implicit conversion is defined in terms of copy-initialization: if an object of type T can be copy-initialized with expression E , then E is implicitly convertible to T . The equals sign, = , in copy-initialization of a named variable is not related to the assignment operator.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With