Starting from C++20 closure types without captures have default constructor, see https://en.cppreference.com/w/cpp/language/lambda:
If no captures are specified, the closure type has a defaulted default constructor.
But what about closure types that capture, how can their objects be constructed?
One way is by using std::bit_cast
(provided that the closure type can be trivially copyable). And Visual Studio compiler provides a constructor for closure type as the example shows:
#include <bit>
int main() {
int x = 0;
using A = decltype([x](){ return x; });
// ok everywhere
constexpr A a = std::bit_cast<A>(1);
static_assert( a() == 1 );
// ok in MSVC
constexpr A b(1);
static_assert( b() == 1 );
}
Demo: https://gcc.godbolt.org/z/dnPjWdYx1
Considering that both Clang and GCC reject A b(1)
, the standard does not require the presence of this constructor. But can a compiler provide such constructor as an extension?
Captures default to const value. By default, variables are captured by const value . This means when the lambda is created, the lambda captures a constant copy of the outer scope variable, which means that the lambda is not allowed to modify them.
Lambdas can both capture variables and accept input parameters. A parameter list (lambda declarator in the Standard syntax) is optional and in most aspects resembles the parameter list for a function. auto y = [] (int first, int second) { return first + second; };
The type of a lambda expression is unspecified. But they are generally mere syntactic sugar for functors. A lambda is translated directly into a functor.
To capture the member variables inside lambda function, capture the “this” pointer by value i.e. std::for_each(vec. begin(), vec. end(), [this](int element){ //.... }
But what about closure types that capture, how can their objects be constructed?
You can't. They can only be created from the lambda expression.
And no, bit_cast
does not "work everywhere". There is no rule in the C++ standard which requires that any particular lambda type must be trivially copyable (or the same size as its capture member for that matter). The fact that no current implementations break your code does not mean that future implementations cannot.
And it definitely won't work if you have more than one capture member.
Just stop treating lambdas like a cheap way to create a type. If you want to make a callable type with members that you can construct, do that:
#include <bit>
int main() {
struct A
{
int x = 0;
constexpr auto operator() {return x;}
};
// ok everywhere
constexpr A b(1);
static_assert( b() == 1 );
}
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