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