指向具有多个参数作为函数参数的函数

时间:2014-11-03 05:32:03

标签: c++ function pointers

我使用来自优化工具箱的函数,该函数以数字方式计算函数的导数。它接受一个带有一个参数的函数的指针,但是如果我需要将一个指针传递给一个带有多个参数的函数,并希望传递额外的,不那么重要的参数呢?

//Function from toolbox
double num_differentation(double (func(const double)), double x)
{
//makes various calls to func, but with only one parameter
func(x);
}

现在假设我有一个函数我想传递给上面的函数,但是其他参数与优化问题没有直接关系,但是需要为函数得到一个有意义的结果。

double my_func_to_be_input(double a, double b, double c) {
return a+b*c;
}

有没有办法重写num_differentiation,以便在调用func时它会通过所有三个参数?我尝试了以下但是没有用:

double num_differentation(double (func(const double arg1, const double arg2, const double arg3)), double x)
{
//makes various calls to func, but with only one parameter
func(x, arg2, arg3);
}

如果我们想要更加花哨,那么num_differentiation是否可以接受具有不同数量参数的函数,而不相关的参数只是被传递?

在任何情况下,我都不想使用全局变量来路由这些附加参数。

我正在使用Visual Studio 2013,欢迎任何有用的建议,尤其是具体的代码示例。

更新 这就是我解决它的方法。

//Rewritten function from toolbox
double rewritten_num_differentation(std::function<double(double)> func, double x)
{
func(x);
}

在我的主要代码中:

using namespace std::placeholders;    
auto my_func_to_be_input_with_forwarded_arguments= std::bind(my_func_to_be_input, _1, second_argument_to_be_forwarded, third_argument_to_be_forwarded);

return rewritten_num_differentiation(my_func_to_be_input_with_forwarded_arguments, x_arg);

这类似于CrazyEdie建议的第一个解决方案。也许还有更优雅的方法不涉及重写工具箱函数,但将std :: function类型转换为C风格的函数指针似乎非常复杂(就像他们在这里尝试http://www.cplusplus.com/forum/general/63552/)。

2 个答案:

答案 0 :(得分:2)

double num_differentials(std::function<double(double)> fun, double x)
{
    return fun(x);
}

auto n = num_differentials(std::bind(&fun, _1, arg1, arg2), x);

或者:

auto n = num_differentials([arg1,arg2](double x) { return fun(x,arg1,arg2); }, x);

我相信两者都应该在VC2013中有效。

编辑以响应更新:

通过C回调系统调用std::function并不是那么难。

假设:

void register_callback(double (*fun)(double,void*), void* client_data);

写下这个:

double wrap_legacy(double d, void* client_data)
{
    auto fun = static_cast<std::function<double(double)>*>(client_data);
    return (*fun)(d);
}

或者如果您想添加一些安全性,请:

double wrap_legacy(double d, void* client_data)
{
    auto any = static_cast<boost::any*>(client_data);
    auto fun = boost::any_cast<std::function<double(double)>>(*any);
    return fun(d);
}

在这里,您只需使用boost::any作为任何和所有此类构造的标准类型。总是施放到任何一个,总是包裹在任何。然后,如果有人搞砸了并发送了错误的数据类型,那么您将获得异常,而不是未定义的行为。

像这样使用:

auto fun = std::function<double(double)>{[](double d) { return d; }};
register_callback(&wrap_legacy, &fun);

或安全版:     auto any = boost :: any {std :: function {[](double d){return d; }}};     register_callback(&amp; wrap_legacy,&amp; fun);

当然,一般来说,client_data生存期要求指向堆分配,因此您需要处理它。还有你可以做的进一步包装,比如包裹register_callback - 这可以提高安全性。

答案 1 :(得分:0)

精心设计的C风格工具箱的原型是:

//Function from toolbox
double num_differentation(double (func(const double, void*)), 
                          double x, 
                          void * user_data)
{
 //makes various calls to func, but with only one parameter
 func(x, user_data);
}

然后期望用户写

typedef struct my_data { int p; } my_data
double func(double x, void * user_data) {
   my_data * data = (my_data*)user_data;
   return pow(x, data->p);
}

你可以像这样使用这个库:

my_data data;
data.p = 7;
num_differentiation(&func, 3.0, &data);

然而,它听起来像是你被困在一个令人讨厌的工具箱,以及&#34;标准&#34;是使用那是使用全局,而不是传递用户数据。

my_data g_data;
double func(double x) {
   return pow(x, g_data.p);
}

然后像

一样使用它
g_data.p=7;
num_differentiation(&func, 3.0);