指向具有多个参数作为函数参数的函数 [英] Pointers to functions with multiple arguments as function arguments

查看:153
本文介绍了指向具有多个参数作为函数参数的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用了一个优化工具箱中的函数,该函数用数值计算函数的导数。它接受一个指向具有一个参数的函数的指针,但是如果我需要将指针传递给一个带有多个参数的函数,并期望其他不太重要的参数能够通过,那该怎么办?

  //工具箱中的函数
double num_differentation(double(func(const double)),double x)
{
/ /对func进行各种调用,但只有一个参数
func(x);

$ / code>

现在假设我有一个函数可以传递给上面的函数其中有额外的参数与优化问题没有直接关系,但仍然需要为函数获得有意义的结果。

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

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

pre $ double num_differentation(double(func(const double arg1,const double arg2,const double arg3)),double x)
{
//对函数进行各种调用,但只有一个参数
func(x,arg2,arg3);

code $


如果我们想要变得更加奇特,是否有可能为num_differentiation接受一个具有不同数量参数的函数,而不相关的函数只是通过了?



在任何情况下,我都不喜欢使用全局变量来路由这些额外的参数。

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



更新:
这就是我解决这个问题的方法。

  //从工具箱重写函数
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/ )。

解决方案

  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中工作。



编辑以响应更新:



对于 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);

$ / code>

或者,如果您想添加一些安全性,请执行以下操作:

  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);
返回乐趣(d);

$ / code>

这里您只需使用 boost :: any code>作为任何和所有这样的结构的标准类型。总是投到任何东西,并始终包裹任何。然后,如果有人搞砸了,并发送错误的数据类型,你会得到异常,而不是未定义的行为。



使用像这样:

  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(& wrap_legacy,& fun);

当然,一般来说,client_data生存期要求指向堆分配,因此您需要处理接着就,随即。还有更多的包装可以做,例如包装 register_callback - 可以增加安全性。


I use a function from an optimization toolbox that numerically calculates derivatives of functions. It accepts a pointer to a function with one argument, but what if I need to pass a pointer to a function with multiple arguments to it and expect the additional, less important parameters to just be passed through?

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

Now assume I have a function I'd like to pass to the above but which has additional arguments not directly related to the optimization problem, but that are nevertheless required to arrive at a meaningful result for the function.

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

Is there a way to rewrite num_differentiation so that at the time of calling func it passes through all three parameters? I tried the following but it did not work:

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

And if we wanted to be even more fancy, would it be possible for num_differentiation to accept a function with varying numbers of parameters with the irrelevant ones just being passed through?

In any case, I would not like to have to resort to global variables to route these additional parameters.

I'm using Visual Studio 2013 and would welcome any helpful suggestions, especially with concrete code examples.

UPDATE: This is how I solved it.

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

In my main code:

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

This is akin to CrazyEdie's suggested first solution. Perhaps there are still more elegant ways that do not involve rewriting the toolbox function, but it seems to be awfully complicated to convert the std::function type to a C-style function pointer (like they try here http://www.cplusplus.com/forum/general/63552/).

解决方案

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

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

alternatively:

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

I believe both should work in VC2013.

Edit in response to update:

It's not all that hard to wrap up a std::function for calling through a C callback system.

Assuming:

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

Write this:

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

Or if you want to add some security, this:

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

Here you just use boost::any as a standard type for any and all such constructs. Always cast to any and always wrap in any. Then if someone screws up and sends the wrong kind of data you'll get exceptions rather than undefined behavior.

Use like this:

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

Or the safe version: auto any = boost::any{std::function{[](double d){ return d; }}}; register_callback(&wrap_legacy, &fun);

Of course, generally speaking the client_data lifetime requirements point to heap allocation so you'll need to deal with that. There's also further wrapping you can do and such--like wrapping up register_callback--that can increase safety.

这篇关于指向具有多个参数作为函数参数的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆