No. Well maybe.
For your particular case, your lambda is just an override set of a single function f
known at instantiation. Override set objects can be created and passed around with type erasure without much of a problem. You just need to manually enumerate the overrides and provide it to the override set.
So if your goal is to just have an object that is the override set of f
, yes, you can do this. See "Manual" signature overload resolution -- add in some type erasure on top of that mess, and bob is your uncle.
The general case, where you have some auto
lambda with arbitrary code within it, no.
The way to envision this problem is imagine a DLL or shared library compiled with your lambda, a second DLL or shared library holding the function
like object, and some other DLL or shared library wanting to call it.
The behavior of what happens when you call the function
is dependent on the definition of the lambda and the type that you want to call it with to an arbitrary degree.
In order for this to work, a nearly complete run time compilation model would have to be available in both the DLL where the lambda was created, and the DLL where the type it is called with, and that run time compilation model would have to be compatible.
This is both not required by the C++ standard, and would make things far more complex if it was, and would eliminate optimization opportunities.
Now, not all is hopeless.
If there is some fixed list of types you want to support, a polymorphic function
signature can be written. This is basically a special case of the 'override set' solution above, and can even be written using it.
On the other hand, if you are willing to type erase the properties of the arguments to your lambda, and type erase, and return some uniform type (be it boost::any
or boost::variant
or whatever), you can do something. You write up a type erasure object type, and expose it. Then you have a std::function< boost::any(type_erasure_object) >
, and the conversion occurs outside the call, and within the call you deal with said type erased object.
Picking overloads using a type erased object is tricky, in that the C++ compiler doesn't help you much with producing a list of overloads to consider. If you collect that list manually, you can even type erase which overload you'll pick.
Pulling that off is possible, but I have not written it before. The alternatives to this are all far easier.
I don't consider the type erased case to solve this problem, as it blocks certain kinds of optimizations. But in theory, it means that you can work with a nearly arbitrary type.
The type erasure object must be exposed to the end user, and it must erase every piece of type information that every lambda you shove into that std::vector
needs to know. So this can significantly restrict what lambdas you are storing in your std::vector
in some cases.
For an example of how to type erase nearly arbitrary objects, look at boost type erasure.
Finally, what you are asking for is rarely an actual requirement of a problem. You would be best to describe your actual, practical problem, which almost certainly has solutions that are not nearly as esoteric as those above.