I want to return a lambda object from a function without casting it to a function pointer or function object. More specifically, I want to leave it to the client to decide whether or not to cast to a function object or retain the lambda as an anonymous function:
template<typename F> // F may be a std::function, boost::function, or lambda object
auto func(F f) -> decltype(???) // what do I put in here?
{
return [=]()
{
return f(someParameter);
}
}
This code doesn't work because I don't know what type to deduce. One option might be to copy the body of the lambda into the decltype
call. Surely there is a better way!
My reasoning for wanting to do it this way is that I want to leave open the possibility of the compiler more intelligently inlining or unwrapping the lambdas. Does this reasoning make sense? If so, why, and when is it better simply to return std::function
? Could this method ever be slower at compile time?
In C++11 you cannot do this. You can do a few things that are close to it, but not this.
Basically, the only way to extract a type of a C++11 lambda is to deduce it from an instance of the type, and you cannot name the type in an unevaluated context. So a function cannot return a type whose type depends on the type of a lambda. (Unless said lambda is declared, with body, prior to the function's declaration, which is not useful in this case). You can write a functor that is a manual function object, or use std::bind
which does that for you.
You can have it evaluate some other functor you also pass in with the lambda, but that gets awkward (especially in C++11 where such functors either have to type erase, or have to be an old-school functor written "manually" as a struct
or class
).
One of the features added in C++1y makes it easy, however:
template<typename F, typename T>
auto func(F f, T t) {
return [=]() {
return f(t);
};
}
int main() {
auto f = func( [](int x){ std::cout << x << "\n"; }, 7 );
f();
f();
}
Live example
It is possible your compiler already has C++1y support for this feature.
In C++11, type-erase with std::function<...>
In C++14 no need for decltype, so you can do:
auto f() {
return //lambda here
}
That's all you can do for now.
Clang claims to have full c++14 support in its version 3.4, as the current draft is. Gcc has support full support for this in upcoming gcc 4.9, and partial support in gcc 4.8.
AFAIK, if you are capturing stuff with the lambda, it can't be represented generally outside a container like std::function
And then, I think the compiler can't inline the returned lambda because it does not exist previous to the function call.
So you generate it, and on execution it loads it's state and do it's thing.
If so, why, and when is it better simply to return std::function?
Why?
It's standard library. Probably as much freedom as the client gets. You can extract a lambda from it, or a function pointer, or a function, etc.
(take a look at target
http://en.cppreference.com/w/cpp/utility/functional/function/target )
When?
When you want to return an encapsulated function.
Does it answer or do I miss your point? Lambdas are so cool, but I fear that I (and many) overestimated them in the beginning of the learning curve (specially performance-wise, treating them like self-generating code voodoo)