2015-07-21 4 views
0

У меня есть математическая функция f(x,p), которая зависит от аргумента x и параметров p. Я хочу динамически выделить память для p (void *) и вернуть функцию g(x) после ввода значений параметров f. Как реализовать это на C++? Более конкретно, это сценарий использования я надеюсь достичь:Возвращение функции после заданных параметров

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

g1(x) и g2(x) являются функциями, которые вычисляют f(x,p1) и f(x,p2) соответственно. Спасибо.

+0

aka currying http://stackoverflow.com/questions/152005/how-can-currying-be-done-in-c – pm100

ответ

2

Что вы просите эффективно «связывать» первый аргумент (p1) к функции (е) и иметь «заполнитель» для второго аргумента (х). Воплощение, что непосредственно в программный код в C++ 11, мы могли бы использовать std::bind:

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

Возвращаемый тип bind не определен, но если вам нужно хранить g1 где вы можете хранить его в качестве std::function<void(double)>.

Или вы могли бы C++ 14 это и написать общий два аргумента-кожевник:

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); 
2

В C++ 11 вы можете использовать лямбда для достижения этой цели:

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); 
0

Есть несколько концептуальных проблем с вашим подходом:

  1. Вы можете вернуть указатель на функцию из функции (вот что вы описываете, что вы хотите сделать здесь: g1 = f (p1)), но я думаю, что это слишком много.
  2. Поскольку g1 (x) = f (x, p1) и g2 (x) = f (x, p2), это звучит так, как будто все, что вам нужно, это f (x, p1) и f (x, p2);

    double x; 
    p1 = new double[2]; 
    p2 = new double[2]; 
    f(x,p1); 
    f(x,p2); 
    
+1

Простой указатель функции не будет работать, потому что OP хочет связать аргумент с функцией. Что касается точки № 2, показанный код может не соответствовать реальному коду. – KABoissonneault

2

Вы можете использовать std::function, инициализированный с помощью лямбда

#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);  
} 
+1

Обратите внимание, что в C++ 14 вы можете вернуть сам лямбда и избежать стоимости 'std :: function'. – Quentin

+0

@Quentin Мне по-прежнему нравится вариант функции std ::, потому что для кого-то, не знакомого с языком, может быть проще, если вы хотите нести функцию вокруг – KABoissonneault

+1

@KABoissonneault, вы все равно можете записать результат в 'std :: function', если вы хотите, но принуждение к тем, кто * знаком с лямбдами, будет плохой идеей. – Quentin

0

Вы можете использовать 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); 
} 
Смежные вопросы