Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic std::function to store a generic lambda [duplicate]

When generic lambda is stored as a std::function, we need to provide a concrete type, something like,

std::function<double(double)>

thus binding to a specific type,

The following declaration:

std::function<auto(auto)>

throws a compiler error.

I understand that, from c++14 onwards, auto can be used to store return value of a lambda, but is there a way to achieve this when storing a lambda in std::function?

like image 952
Rajesh Avatar asked Dec 18 '18 08:12

Rajesh


2 Answers

You can't. Not even with a custom wrote std::function. This is a fundamental limit of type erasure.

Intuitively, templates requires the type information available at the point of function call but type erasure in std::function destroys that information.

On a more detailed level, type erasure works by storing the set of operations in a type-agnostic way at compile-time, either implicitly by virtual functions or explicitly by function pointers. Templates are effectively an infinite family of operations and is thus impossible to be stored.

If you know the fixed set of function signatures you will be using, you can write a custom std::function.

like image 75
Passer By Avatar answered Oct 05 '22 11:10

Passer By


You can't.

Generic lambda and std::function are completely different things.

You can rougly see an auto(auto) lambda as a not-template class with a template operator().

Something as

struct myUnnamedLambdaStruct
 {
   // ...

   template <typename T>
   auto operator() (T t) const 
    { /* .... */ };
 };

Where std::function() is the contrary: it's a (specialization of a) template class with a not-template operator()

template <typename>
class function;

template <typename RetType, typename ... ArgTypes>
class function<RetType(ArgTypes...)>
 {
   // a lot of other members/methods

   public:
      RetType operator() (ArgTypes ... args) const
       { /* .... */ }
 };

So a generic lambda object doesn't contain a single operator() but a set of operator() where a std::function object contain a single operator().

You can "save" a generic lambda in a std::function but only fixing, one time for all, the RetType and the ArgTypes.... That is: selecting a single operator(), in the available set of operator()s, and forgetting all the others.

like image 33
max66 Avatar answered Oct 05 '22 13:10

max66