C++: pass function with arbitrary number of parameters as a parameter

不问归期 提交于 2019-11-28 12:09:06

What you need is templates and std::bind() (or its boost::bind() counterpart if you can't afford C++11). For instance, this is what your trap() function would become:

template<typename F>
double trap(F&& f, double a, double b) {
  int N = 10000;
  double step = (b-a)/N;
  double s = 0;
  for (int i=0; i<=N; i++) {
    double xi = a + i*step;
    if (i == 0 || i == N) { s += f(xi); }
//                               ^
    else { s += 2* f(xi); }
//                 ^
  }
  s *= (b-a)/(2*N);
  return s;
}

Notice, that we are generalizing from function pointers and allow any type of callable objects (including a C++11 lambda, for instance) to be passed in. Therefore, the syntax for invoking the user-provided function is not *f(param) (which only works for function pointers), but just f(param).

Concerning the flexibility, let's consider two hardcoded functions (and pretend them to be meaningful):

double foo(double x)
{
    return x * 2;
}

double bar(double x, double y, double z, double t)
{
    return x + y * (z - t);
}

You can now provide both the first function directly in input to trap(), or the result of binding the last three arguments of the second function to some particular value (you have free choice on which arguments to bind):

#include <functional>

int main()
{
    trap(foo, 0, 42);
    trap(std::bind(bar, std::placeholders::_1, 42, 1729, 0), 0, 42);
}

Of course, you can get even more flexibility with lambdas:

#include <functional>
#include <iostream>

int main()
{
    trap(foo, 0, 42);
    trap(std::bind(bar, std::placeholders::_1, 42, 1729, 0), 0, 42);

    int x = 1729; // Or the result of some computation...
    int y = 42; // Or some particular state information...
    trap([&] (double d) -> double
    {
        x += 42 * d; // Or some meaningful computation...
        y = 1; // Or some meaningful operation...
        return x;
    }, 0, 42);

    std::cout << y; // Prints 1
}

And you can also pass your own stateful functors tp trap(), or some callable objects wrapped in an std::function object (or boost::function if you can't afford C++11). The choice is pretty wide.

Here is a live example.

What you trying to do is to make this possible

trap( quad, 1, 2, 3, 0, 1 );

With C++11 we have alias template and variadic template

template< typename... Ts >
using custom_function_t = double (*f) ( double, Ts... );

above define a custom_function_t that take a double and variable numbers of arguments.

so your trap function becomes

template< typename... Ts >
double trap( custom_function_t<Ts...> f, Ts... args, double a, double b ) {
    int N = 10000;
    double step = (b-a)/N;
    double s = 0;
    for (int i=0; i<=N; i++) {
        double xi = a + i*step;
        if (i == 0 || i == N) { s += f(xi, args...); }
        else { s += 2*f(xi, args...); }
    }
    s *= (b-a)/(2*N);
    return s;
}

Usage:

double foo ( double X ) {
  return X;
}

double quad( double X, double A, double B, double C ) {
  return(A*pow(x,2) + B*x + C);
}

int main() {
  double result_foo  = trap( foo, 0, 1 );
  double result_quad = trap( quad, 1, 2, 3, 0, 1 );  // 1, 2, 3 == A, B, C respectively
}

Tested on Apple LLVM 4.2 compiler.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!