c++ 如何使用std::function来接受一个具有不同参数的函数?

wbgh16ku  于 2023-03-20  发布在  其他
关注(0)|答案(4)|浏览(122)

我有两个函数,first_functionsecond_function,它们有相似的签名。second_function有两个额外的参数,x, y
我想创建另一个函数,它可以接受first_functionsecond_function作为参数。
我想使用std::function,但似乎这只限于具有相同返回类型和相同参数的输入函数?有没有办法让它在我的情况下工作?
这里有一个最小的例子,我试图实现什么:

void first_function(double z) {
  // Implementation not included
}

void second_function(double x, double y, double z) {
  // Implementation not included
}

void compute(first_or_second_function, std::optional<double> x, std::optional<double> y, double z) {

  if (x.has_value()) {
    // invoke second function
    first_or_second_function(x.value, y.value(), z);
  } else {
    // invoke first function
    first_or_second_function(z);
  }

}

我不确定如何创建参数first_or_second_function

waxmsbnn

waxmsbnn1#

你不能自己写一个简单的functionoid吗?

struct function_overloader {
    void operator()(double z) const {
       first_function(z);
    }
    void operator()(double x, double y, double z) const {
       second_function(x, y, z);
    }
};
//and then just use this instead of `std::function<....>`

如果希望函数是可替换的,则:

struct function_overloader {
    std::function<void(double)> first_function;
    std::function<void(double,double,double)> second_function;

    void operator()(double z) const {
       first_function(z);
    }
    void operator()(double x, double y, double z) const {
       second_function(x, y, z);
    }
};
//and then just use this instead of `std::function<....>`
koaltpgm

koaltpgm2#

您可以使用std::variant将函数作为单个参数传入。

#include <iostream>
#include <optional>
#include <variant>

using std::cout;
using std::get;
using std::optional;
using std::variant;

namespace {

void first_function(double z) {
    cout << "first_function z:" << z << "\n";
}

void second_function(double x, double y, double z) {
    cout << "first_function x:" << x << " y:" << y << " z:" << z << "\n";
}

using Fn1_t = void(*)(double);
using Fn3_t = void(*)(double,double,double);
using Fn_t = variant<Fn1_t, Fn3_t>;

void compute(Fn_t fn, optional<double> x, optional<double> y, double z) {
    if (x.has_value() && y.has_value()) {
        get<1>(fn)(x.value(), y.value(), z);
    } else {
        get<0>(fn)(z);
    }
}

} // anon

int main() {
    compute(&first_function, {}, {}, 10.0);
    compute(&second_function, 8.2, 9.1, 10.0);
}
oug3syen

oug3syen3#

我有点不确定为什么你要把它传递给一个函数,让函数来决定,而不是在你提供的if语句中自己调用每个函数。
我相信您正在寻找的代码应该是这样的:

#include <iostream>
using namespace std; // Shouldn't use this, only for example purposes.

template<typename... Args>
void myFunc(Args... args) {
  cout << "myFunc called with " << sizeof...(args) << " arguments." << endl;
}

template<typename... Args>
void otherFunc(Args... args) {
  cout << "otherFunc called with " << sizeof...(args) << " arguments." << endl;
}

template<typename Func, typename... Args>
void callFunc(Func func, Args... args) {
  func(args...);
}

int main() {
  callFunc(&myFunc<double>, 1.0);
  callFunc(&otherFunc<double, double, double>, 1.0, 2.0, 3.0);
  return 0;
}

我不确定我是否会 * 推荐 * 这个解决方案,但它应该会起作用。
运行上述代码的输出:

myFunc called with 1 arguments.
otherFunc called with 3 arguments.

您还应该查看:C++ template function with unknown number of arguments(如果不熟悉模板函数)。

o2g1uqev

o2g1uqev4#

一个简单的重载compute()就可以了。

void compute(double x, double y, double z) {
   second_function(x, y, z);
}

void compute(double z) {
   first_function(z);
}

基本上提供了与具有可变参数的函数一样多的compute()重载。
您甚至可以使用if constexpr根据传入的参数数量对compute()进行模板化,如下所示

void first_function(double z) {
    std::cout<<"first_function\n";
}

void second_function(double z, double x, double y) {
    std::cout<<"second_function\n";
}
template <typename ...Args>
void compute(Args... args) {
    if constexpr(sizeof...(args) == 3) {
        second_function(args...);
    } else if constexpr(sizeof...(args) == 1) {
        first_function(args...);
    } else {
        static_assert(false, "no function implemented");
    }
}

int main() {
    compute(1);
    compute(1,2,3);
    compute(1,2); // Fail to compile
}

相关问题