Zhiltsoff Igor
Zhiltsoff Igor

Reputation: 1822

C++: implementing a higher-order function which receives a lambda as an input

Let's take a look at the following function:

auto F(vector <int> *p) {
  return [p](int y) -> int{ return y + (*p)[0]; };
}

It does a pretty simple thing: it receives a pointer at a vector of integers and returns a lambda which has another integer as an input and returns the result of adding this integer to the first element of the vector we have a pointer at. If I want to implement a higher-order function which could accept such a lambda as input, I, obviously, cannot use the auto in the prototype. I tried fixing it like this:

typedef int *A (int);

A F(vector <int> *p) {
      return [p](int y) -> int{ return y + (*p)[0]; };
    }

But that implementation brings about a conflict as well: the lambda type cannot be converted to A.

How could this be implemented?

Upvotes: 1

Views: 590

Answers (2)

Useless
Useless

Reputation: 67743

I tried fixing it like this:

typedef int *A (int);

A F(vector <int> *p) {
      return [p](int y) -> int{ return y + (*p)[0]; };
}

... the lambda type cannot be converted to A.

This would make sense in principle only for a completely stateless lambda. Your lambda has a capture, which means it has state that needs to be stored somewhere, which means it must be a callable object rather than a simple free function.

Your options are:

  1. Implement the higher-order function as a template on the lower-order type:

    template <typename Func>
    int higherOrder(int x, Func&& f)
    {
      return f(x);
    }
    

    or

  2. Wrap the lambda inside something with a well-known type, usually

    int higherOrder(int x, std::function<int(int)> const &f)
    {
      return f(x);
    }
    

Upvotes: 5

Brian Bi
Brian Bi

Reputation: 119219

You can use a template:

template <class Func>
void foo(Func func);

foo(F(p));  // ok; Func deduced to the lambda type

Upvotes: 2

Related Questions