I want a way to make functor from function. Now I trying to wrap function call by lambda function and instantiate it later. But compiler says than lambda constructor is dele
We can assume that the lambda will always be empty, thus, we can just do a cast from another empty type, since they both have the same memory layout. So we build a wrapper class that makes a default constructible function object:
template<class F>
struct wrapper
{
static_assert(std::is_empty<F>(), "Lambdas must be empty");
template<class... Ts>
auto operator()(Ts&&... xs) const -> decltype(reinterpret_cast<const F&>(*this)(std::forward<Ts>(xs)...))
{
return reinterpret_cast<const F&>(*this)(std::forward<Ts>(xs)...);
}
};
Now a static assert is added to make sure that the lambda is always empty. This should always be the case(since its required to decay to a function pointer), but the standard doesn’t explicitly guarantee it. So we use the assert to at least catch the insane implementation of lambdas. Then we just cast the wrapper class to the lambda since both of them are empty.
Finally the lambda could be constructed like this:
template <class F>
void function_caller()
{
wrapper<F> f;
f();
}
Lambdas do not have default constructors. Ever. The only constructors they sometimes give access to is (depending on what they capture) the copy and/or move constructors.
If you create a functor with no public default constructor, you'll get the same error.
In C++17 you can solve this with constexpr
lambda and operator+
to decay-to-function pointer. A type that carries a function pointer and invokes it is easy with auto
template parameters.
In C++11 you gotta get a bit hacky.
template<class F>
struct stateless_lambda_t {
static std::aligned_storage_t< sizeof(F), alignof(F) >& data() {
static std::aligned_storage_t< sizeof(F), alignof(F) > retval;
return retval;
};
template<class Fin,
std::enable_if_t< !std::is_same< std::decay_t<Fin>, stateless_lambda_t >{}, int> =0
>
stateless_lambda_t( Fin&& f ) {
new ((void*)&data()) F( std::forward<Fin>(f) );
}
stateless_lambda_t(stateless_lambda_t const&)=default;
template<class...Args>
decltype(auto) operator()(Args&&...args)const {
return (*static_cast<F*>( (void*)&data() ))(std::forward<Args>(args)...);
}
stateless_lambda_t() = default;
};
template<class F>
stateless_lambda_t<std::decay_t<F>> make_stateless( F&& fin ) {
return {std::forward<F>(fin)};
}
Now we can:
auto t = make_stateless([]{ func(); });
and your code works.
A static_assert
or SFINAE that the F
is actually an empty type might be a good idea. You know, for quality.
The use of C++14 features can be replaced with manual decltype
and spewing typename
and ::type
keywords. This answer was originally written for a C++14 question that was closed as a duplicate of this one.
live example.
No.
However I believe that lambdas can be copied, so your functor_caller
could take an argument to initialize its attribute.
Still, instead of reinventing the wheel, I would use std::function
instead.
The code doesn't make sense. Imagine you have a capturing lambda like this:
{
int n = 0;
auto t = [&n](int a) -> int { return n += a; };
}
What could it possibly mean to default-construct an object of type decltype(t)
?
As @Matthieu suggests, you could wrap the lambda into a function
object:
std::function<int(int)> F = t;
Or you could template your call-site directly on the type of the lambda (or any callable entity):
template <typename F>
int compute(int a, int b, F f)
{
return a * f(b); // example
}
Usage: int a = 0; for (int i : { 1, 3, 5 }) { a += compute(10, i, t); }
If at all possible, the second style is preferable, since the conversion to std::function
is a non-trivial, potentially expensive operation, as is the actual function call through the resulting object. However, if you need to store a uniform collection of heterogeneous callable entities, then std::function
may well be the easiest and most convenient solution.