0

I have a mathematical function f(x,p) that depends on argument x and parameters p. I want to dynamically allocate memory for p ( void *) and return a function g(x) after the parameters values are fed f. How do I implement this in C++? More specifically, this is the usage scenario I'm hoping to achieve:

 double x;
 p1 = new double[2];
 p2 = new double[2];
 g1 = f(p1)
 g2 = f(p2)
 g1(x);
 g2(x);

g1(x) and g2(x) are functions that compute f(x,p1) and f(x,p2), respectively. Thank you.

TartanLlama
  • 63,752
  • 13
  • 157
  • 193

5 Answers5

2

In C++11 you can use a lambda to achieve this:

double x;
auto p1 = new double[2];
auto p2 = new double[2];
auto g1 = [p1](double d){return f(d,p1)};
auto g2 = [p2](double d){return f(d,p2)};
g1(x);
g2(x);
TartanLlama
  • 63,752
  • 13
  • 157
  • 193
2

What you're asking is effectively to "bind" the first argument (p1) to a function (f) and to have a "placeholder" for the second argument (x). Translating that directly into code in C++11, we could use std::bind:

auto g1 = std::bind(f, p1, std::placeholders::_1);
g1(x); // calls f(p1, x);

The return type of bind is unspecified, but if you need to store g1 somewhere you could store it as a std::function<void(double)>.

Or you could C++14 it up and write a generic two-argument currier:

template <typename F, typename Arg>
auto curry(F f, Arg arg) {
    return [f,arg](auto arg2) {
        return f(arg, arg2);
    };
}

auto g1 = curry(f, p1);
g1(x);
Barry
  • 286,269
  • 29
  • 621
  • 977
2

You can use a std::function, initialized with a lambda

#include <functional>

std::function<void (double)> f(double *p)
{
    return [&](double x) {
        // whatever
    };
}

int main()
{
    double *p = new double[2];

    auto g = f(p);
    g(2);    
}
JorenHeit
  • 3,877
  • 2
  • 22
  • 28
  • 1
    Note than in C++14 you can return the lambda itself and avoid the cost of `std::function`. – Quentin Jul 21 '15 at 15:12
  • @Quentin I still like the option of returning an std::function, because it might be simpler for someone not much familiar with the language if you want to carry the function around – KABoissonneault Jul 21 '15 at 15:13
  • 1
    @KABoissonneault you can still sotre the result in a `std::function` if you wish, but forcing it upon those who *are* familiar with lambdas would be a bad idea. – Quentin Jul 21 '15 at 15:14
0

There are a few conceptual problems with your approach:

  1. You can return a function pointer from a function (this is what you describe you want to do here: g1 = f(p1) ), but I think that's overkill here.
  2. Since g1(x) = f(x,p1) and g2(x) = f(x,p2) it sounds like all you need is f(x,p1) and f(x,p2);

    double x;
    p1 = new double[2];
    p2 = new double[2];
    f(x,p1);
    f(x,p2);
    
Pandrei
  • 4,843
  • 3
  • 27
  • 44
  • 1
    A simple function pointer wouldn't work, because OP wants an argument binded to the function. As for point #2, the shown code might not correspond to the actual code. – KABoissonneault Jul 21 '15 at 15:05
0

You can use std::bind

#include <iostream>
#include <functional>

void f(double x, double p[2])
{
    std::cout << x << " " << p[0] << " " << p[1] << std::endl;
}

int main() {
    double x = 5;
    auto p1 = new double[2];
    p1[0] = p1[1] = 10;
    auto p2 = new double[2];
    p2[0] = p2[1] = 20;
    auto g1 = std::bind(f, std::placeholders::_1, p1);
    auto g2 = std::bind(f, std::placeholders::_1, p2);
    g1(x);
    g2(x);
}
Yola
  • 18,496
  • 11
  • 65
  • 106