In the following, one way of initialising a member is accepted and the other is an error. I don't understand:
template <typename T>
struct LambdaHolder
{
LambdaHolder(T lambdaIn) { lambda = lambdaIn; } // This will not work
LambdaHolder(T lambdaIn) : lambda(lambdaIn) { } // This will work fine
T lambda;
};
int main()
{
auto lambda = []() { return 0; };
LambdaHolder<decltype(lambda) > foo(lambda); // This will work only if the constructor argument is assigned in the initialiser list
// On the other hand
int(*lambdaPtr)() = lambda; // A function pointer
LambdaHolder<decltype(lambdaPtr)> foo(lambdaPtr); // Will work either in initialiser list or constructor body
}
I'm not understanding a couple of things. I know that certain members must be initialised in the member initialiser list, like references and const members. What I don't understand is why it will let me copy the lambda in the initialiser list but not in the constructor body. The error is "you cannot construct a copy of a lambda".
Also, I was able to create a pointer to the lambda, and initialising the pointer in either the initialiser list or the constructor body worked. Now, I know that lambdas and function pointers aren't exactly the same type, but the thing is that I thought that a captureless lambda is implemented as a free function, which is why you can set a normal function pointer to it, and also thought that when passing as an argument it would definitely decay to a pointer.
Basically I would like some clarification this, what's the difference for the distinction between initialising in the constructor body or initialiser list?
Edit: It seems, as Whoan has pointed out, that a lambda's default constructor's deleted before C++14, and non-existent after C++14 I think.
class 'Foo': no copy constructor available or copy constructor is declared 'explicit' I've made the lambda mutable because I didn't want capture a const Foo, but what I think is happening is that the lambda can't be copied. Another compiler had a more useful error message:
This translates directly into a lambda (rafix07's answer explains how), because it captures Foo by value. The lambda itself is fine. For example, you can write But lambda's move constructor is ill-formed, and in C++11/14 it has to be well-formed for the line
If you don't provide a constructor for your class, C# creates one by default that instantiates the object and sets member variables to the default values as listed in the Default Values Table.
A lambda object is really just an instance of an anonymous class (referred to as a ClosureType) that has a call operator ( operator ()) defined on it. This is a bit strange since C++ doesn't allow you to create anonymous classes explicitly, but it's analogous to anonymous classes in Java .
That is because lambdas are not Default Constructible:
Closure types are not DefaultConstructible. Closure types have "a deleted (until C++14) | no (since C++14)" default constructor.
In this constructor:
LambdaHolder(T lambdaIn) { lambda = lambdaIn; } // This will not work
...lambda
needs to have been default constructed before being assigned.
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