-1

I would like to assign a pointer to a lambda function, in which the lambda function is taking variables passed by reference, not by value.

int main() {
    // what I can do, but not quite what I want
    auto funcy = [](const double i ) {
        std:: cout << "this is i: " << i << std::endl;
    };

    void(*lptr)(double); // OK
    lptr = funcy;
    lptr(1);

    // TODO: make a variable that points to this lambda work
    auto funcy2 = [](const double &i ) {
        std:: cout << "this is i: " << i << std::endl;
    };

    void(*lptr2)(double *);  // BROKE
    lptr2 = funcy2;
    lptr2(1);

    return 0;
}

Is it possible to do this?

Thanks for your time.

Edit: This post is different from Passing capturing lambda as function pointer because I have no idea what that one is saying.

GeneralCode
  • 794
  • 1
  • 11
  • 26
  • Did you try `void(*lptr2)(double const&);`? – Eljay Jul 26 '20 at 23:21
  • 2
    Your function pointer signature doesn't match. It's pretty straightforward. – sweenish Jul 26 '20 at 23:21
  • @Eljay that does not work – GeneralCode Jul 26 '20 at 23:23
  • @sweenish could you provide an example of how straight forward it is? – GeneralCode Jul 26 '20 at 23:24
  • `void (*lptr2)(const double&);` Note in your question, you're trying to assign funcy2 to lptr and not lptr2. You just literally need to make the signatures match. – sweenish Jul 26 '20 at 23:25
  • @sweenish thanks. I fixed the post, and I see what you mean by pretty straight forward. I guess where I managed to get confused was for some reason `void(*lprt)(double)` and `void(*ptr)(const double)` both work. Why does `*lptr2` need the additional `const` added? – GeneralCode Jul 26 '20 at 23:33

2 Answers2

0

Answered by @sweenish in the comments. The "function signature" has to match. It's actually "pretty straightforward".

    void(*lptr2)(const double&);  // FIXED
    lptr2 = funcy2;
    lptr2(5);
GeneralCode
  • 794
  • 1
  • 11
  • 26
  • 1
    To answer your question the `const` is important here specifically because your parameter is is a reference. Capture by value or const value (literally pointless) are treated as interchangeable because they both make copies. – sweenish Jul 26 '20 at 23:46
  • @sweenish Okay yes that makes sense. I see why it would be pointless; makes perfect sense now. Thank you. – GeneralCode Jul 26 '20 at 23:48
0

The best would be that the type of the function pointer would match the type of the lambda function. This will be much more simple and is most likely the solution that you want.

By using pointers everywhere

auto funcy2 = [](double *i) {
    std::cout << "this is i: " << *i << std::endl;
};

void(*lptr2)(double *);  // matches
lptr2 = funcy2;
double i = 1;
lptr2(&i);

... or even better, references everywhere:

auto funcy2 = [](const double &i) {
    std::cout << "this is i: " << i << std::endl;
};

void(*lptr2)(const double &);  // works, the type match the lambda parameter
lptr2 = funcy2;
lptr2(1);

If you really want to assign a lambda to a mismatched type, you'll have to wrap it. Since there's a conversion to do, you can do it using another lambda:

static auto funcy2 = [](const double &i) {
    std::cout << "this is i: " << i << std::endl;
};

auto funcy3 = [](double* i) {
    funcy2(&i); // convert the pointer to a reference
};

void(*lptr2)(double *);  // BROKE
lptr2 = funcy2;
lptr2(1);
Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141