2

I am using Visual Studio 2015. My problem is when I run this it compiles and runs no problem:

typedef double Fct(double);

struct Function {
    Function(Fct f) { cout << f(1) << endl; };
 };

double double_func(double x, double n) { return x + n; }

int main() {
   for(int n = 0; n < 50; ++n)
      Function e{ [](double x) { return double_func(x,1); } }
}

The thing is I want to have this part:

Function e{ [](double x) { return double_func(x,1); } }

To have a capture argument like this:

typedef double Fct(double);

struct Function {
    Function(Fct f) {};
 };

double double_func(double x, double n) { return x + n; }

int main() {
   for(int n = 0; n < 50; ++n)
      Function e{ [n](double x) { return double_func(x,n); } }
}

But I get this error: no instance of constructor "Function::Function" matches the argument list argument types are: (lambda []double (double x)->double)

  • Possible duplicate of [Passing lambda as function pointer](http://stackoverflow.com/questions/28746744/passing-lambda-as-function-pointer) – LogicStuff Jan 27 '17 at 22:29

2 Answers2

3

Edit: Removed Example 1. Doesn't work anymore. :(

Lambdas are actually more a class with a operator() implemented. If you want to save a captured one, you have to store it as an object function pointer:

int first = 5;
auto lambda = [=](int x, int z) {
    return x + z + first;
};
int(decltype(lambda)::*ptr)(int, int)const = &decltype(lambda)::operator();
std::cout << "test = " << (lambda.*ptr)(2, 3) << std::endl;

If you want to return this function and execute it from somewehere else. (Which is actually possible with lambdas) you have to save the object:

// OT => Object Type
// RT => Return Type
// A ... => Arguments
template<typename OT, typename RT, typename ... A>
struct lambda_expression {
   OT _object;
   RT(OT::*_function)(A...)const;

   lambda_expression(const OT & object)
      : _object(object), _function(&decltype(_object)::operator()) {}

   RT operator() (A ... args) const {
      return (_object.*_function)(args...);
   }
};

auto capture_lambda() {
  int first = 5;
  auto lambda = [=](int x, int z) {
    return x + z + first;
  };
  return lambda_expression<decltype(lambda), int, int, int>(lambda);
}
Noxxer
  • 952
  • 6
  • 9
  • Excellent @Noxxer! I've been googling and googling. Nothing clear. This is clear. And it works. Note that in the 1st (of 3) examples, I did have to prepend a decltype(lambda):: to *ptr, but the 2nd and (most importantly) 3rd examples worked as is. I just had to cobble together a 2 liner main for the 3rd, but that was a reasonable drill. Thank you. – davernator Jul 18 '19 at 21:43
  • Your welcome and thank you for the nice comment. You find "a better implementation" for the third example here at the end of my answer: https://stackoverflow.com/questions/28746744/passing-capturing-lambda-as-function-pointer/41528436#41528436 – Noxxer Jul 20 '19 at 04:51
0

Fct is not a super type of the lambda you're trying to pass. (Roughly because function pointers take up less storage than this kind of lambda) You probably want to use std::function<...> as the type for Fct, and not a typedef'd function pointer.

nmr
  • 16,625
  • 10
  • 53
  • 67