How can I instantiate a lambda closure type in C++11/14?
Although this feature is coming in C++20 (see songyuanyao's answer), you don't actually need that in this case. You can just pass the lambda as a function parameter of type FuncType
and call that multiple times:
template <typename FuncType>
std::pair<int,int> DoSomething(FuncType f)
{
return f(std::make_pair(1,1));
}
int main()
{
auto myLambda = [](std::pair<int,int> x) {
return std::make_pair(x.first*2,x.second*2);
};
std::pair<int,int> res = DoSomething(myLambda);
}
I'm aware that there's no default constructor for lambda closure type.
Yes, this is true until C++20. (Note that since C++20 if no captures are specified, the closure type has a defaulted default constructor.)
Closure types are not DefaultConstructible. Closure types have
a deleted (until C++14)
no (since C++14)
default constructor. (until C++20)
And
How does the standard library make it work when
decltype(myLambda)
is passed to something likestd::map
comparators in the template parameter?
There's nothing special for the standard library. If you specify a non-DefaultConstructible lambda as the comparator type for std::map
, you have to pass an object to the constructor, std::map
will initialized its comparator via copy; lambda has copy and move constructor.
You can change your code to the same way as std::map
's constructor:
template <typename FuncType>
std::pair<int,int> DoSomething(const FuncType& f = FuncType()) {
// auto z(f); // you can take a copy if necessary
return f(std::make_pair(1,1));
}
then
auto myLambda = [](std::pair<int,int> x) {
return std::make_pair(x.first*2,x.second*2);
};
std::pair<int,int> res = DoSomething<decltype(myLambda)>(myLambda);
As others have pointed out, empty lambdas will become default-constructible in C++20.
You cannot wait for / switch to it?
No problem, it's easily emulated, as long as your lambda isn't generic.
Simply convert the lambda to a function-pointer, and pack that into a std::integral_constant
:
template <class T>
constexpr auto make_constant(T t) noexcept
-> std::integral_constant<decltype(+t), +t>
{ return {}; }
Of course, in most cases where you can choose a function-objects type, you can also pass the initial value, which is a bit easier.