简体   繁体   中英

function pointers and arbitrary parameters

Imagine I want to write a function that does something with the values of two functions (like a comparison, as example).

f1 and f2 are examples, but it should work for more functions, independent of number and type of arguments.

double f1 (double x, double y, double z) {
    return pow(x,3)+2*pow(y,2)+3*z;
}

double f2 (std::vector<double> vec) {
    double result;
    for (int i=0; i<vec.size(); i++){
        result += vec[i];
    }
    return result;
}

Now I want a compare function that I can call like this (or similar):

int main() {
    std::vector<double> example_vector {1,3,3,7};
    compare(f1, {4, 5, 6}, f2, example_vector);
    return 0
}

and inside compare it will call f1 with x=4, y=5, z=6 and f2 with vec=example_vector.

EDIT:

Here is the solution I used in the end:

#include <iostream>
#include <tuple>
#include <utility>
#include <math.h>
#include <vector>

template<typename FuncA, typename FuncB, typename ...FA_Params, typename ...FB_Params>
void do_sth(FuncA &func_a, FuncB &func_b, const std::tuple<FA_Params ...> &a_params, const std::tuple<FB_Params ...> &b_params) {
    std::cout << std::apply(func_a, a_params) << std::endl;
    std::cout << std::apply(func_b, b_params) << std::endl;
}

//f1, f2 and f3 are example functions

double f1 (double x, double y, double z) {
    return pow(x,3)+2*pow(y,2)+3*z;
}

double f2 (std::vector<double> vec) {
    double result;
    for (int i=0; i<vec.size(); i++){
        result += vec[i];
    }
    return result;
}

double f3 (double a, double omega, double t, double delta) {
    double result;
    result = a*sin(omega*t+delta);
}

int main() {
    do_sth(f1, f2, std::make_tuple(1.0, 2.3, 1.3), std::make_tuple(std::vector<double>{1.0, 2, 3}));
    return 0;
}

C++20 doesn't work for me yet and this needs only C++17.

do_sth should be able to take any functions

I can't see the target here, so it's hard to make it a generic solution, but basically you can do something like that:

template<typename FuncA, typename FuncB>
void compare(FuncA func_a, const std::vector<double> &vec_a, FuncB func_b, const std::vector<double> &vec_b) {
    double res1 = func_a(vec_a[0], vec_a[1], vec_a[2]);
    double res2 = func_b(vec_b);
    // Do something...
}

There are probably more generic solutions to do what you want, but you'll have to clarify your target.

By the way, about f2 :

double f2(std::vector<double> vec);

You can pass the vector by reference / const reference to avoid data copy:

double f2(const std::vector<double> &vec);

EDIT - Solve using variadic function

A little bit more generic approach could be:
compare(f1, f2, std::vector<double>{1.0, 2, 3}, 1.0, 2.3, 1.3);

The call may look something like this:

 compare(f1, f2, std::vector<double>{1.0, 2, 3}, 1.0, 2.3, 1.3);

But the most important thing to notice, is that you can't combine two variadic params in the same function, so one of the functions you pass into this function should accept a single param (in this example, func_b).


EDIT - Solve using std::apply support

As @fT3g0 idea to use tuples for multiple values, here is my version for c++20: Pass params as std::tuples/std::arrays/std::pair/anything that support std::apply implementation

 template<typename Type> concept ApplySupporter = requires (Type t) { { std::get<std::tuple_size<Type>() - 1>(t) }; { std::tuple_size<Type>() }; }; template<typename FuncA, ApplySupporter FA_Params, typename FuncB, ApplySupporter FB_Params> void compare(FuncA func_a, FA_Params a_params, FuncB func_b, FB_Params b_params) { std::cout << std::apply(func_a, a_params) << std::endl; std::cout << std::apply(func_b, b_params) << std::endl; }

Read About

std::apply
concepts
std::get
std::tuple_size

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM