6

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?

max66
  • 65,235
  • 10
  • 71
  • 111
Rajesh
  • 356
  • 1
  • 5
  • 15
  • 6
    This `std::function` should be callable somehow. (It overloads `operator()`.) How do you intend to do it if the signature is unknown? – Scheff's Cat Dec 18 '18 at 08:07
  • 8
    Even if you can store such functors, you can't use them anyway. If one needs two string parms and one needs only an int, how you call them? What kind of software design you have in mind? It looks you have a general design problem, not a problem to store something ;) – Klaus Dec 18 '18 at 08:11
  • 1
    you can't do it with a std::function, you can do it with a template and store T in your class, then you can construct your class with a generic lambda [](auto arg) {/* return something*/}; – Bob Bills Dec 18 '18 at 08:32

2 Answers2

4

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.

Passer By
  • 19,325
  • 6
  • 49
  • 96
2

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.

max66
  • 65,235
  • 10
  • 71
  • 111