将一个函数传递给另一个函数,其中参数的数量可以不同C++
Passing a function to another function in C++ where the number of arguments can be different
我正在C++17中处理一个问题,我正在构建一个根求解器,允许用户将用户定义的函数传递给根求解函数。 下面显示了.cpp
文件的类示例,原型位于.hpp
文件中。
// root.cpp
double RootSolver::newton(double guess, double right_side,
double (*func)(double),
double unc, int iter)
/**
Finds a specific root of a function using the Newton iteration
method
@param guess An initial guess for the value of the root
@param right_side The value of the right side of the
function.
@param func The function for which the root will be
determined
@param unc The uncertainty or tolerance in the accepted
solution. Defaulted to 0.001
@param iter The number of iterations to try before the
function fails. Defaulted to 150.
@return root
*/
{
double x1, x2, x3, y1, y2, slope;
x1 = guess;
x2 = x1 + 0.0000001;
for (int i = 0; i < iter; i++)
{
y1 = func(x1) - right_side;
y2 = func(x2) - right_side;
slope = (y2 - y1) / (x2 - x1);
x3 = x1 - (y1 / slope);
if (func(x3) - right_side <= unc and
func(x3) - right_side >= -unc) return x3;
x1 = x3;
x2 = x1 + 0.0000001;
}
exit_program(iter);
}
// ================================================================
// RootSolver PRIVATE FUNCTIONS
[[noreturn]] void RootSolver::exit_program(int iter)
{
std::string one("Function did not converge within ");
std::string two(" iterations");
std::cout << one << iter << two << std::endl;
exit (EXIT_FAILURE);
}
主文件如下所示;
double func1(double x);
double func2(double x, double a, double b);
int main() {
RootSolver q;
double guess = 2.0;
double right_side = 0.0;
// This function works fine
result = q.newton(guess, right_side, func1)
// - Not sure how to reformat RootSolver.newton so
I can pass it func1 as well as func2 so it can
accept the arguments a and b
return 0;
}
double func1(double x)
{
return pow(x, 6) - x - 1.0;
}
double func2(double x)
{
return pow(x, 6) - a * x - b * 1.0;
}
上面显示的代码非常适合 func1,因为x
是唯一的参数; 但是,我不确定如何重新格式化RootSolver.newton
函数,因此它将采取func1
,除了x
之外没有参数并接受func2
和参数a
和b
。 有谁知道如何将参数传递给函数newton
,使其不针对特定输入函数进行硬编码?
根据松散的描述,听起来调用方 lambda 解决了您的问题:
result = q.newton(guess, right_side, [](double x) {
return func2(x, 0, 0); // Replace 0s with values of a and b.
});
此 lambda 根据需要转换为double(*)(double)
。请注意,如果需要捕获某些内容,这将不起作用,因为函数指针无法存储其他状态。有两种简单的方法可以解决这个问题。
制作一个模板(并将定义放在标题中):
template<typename F> // requires std::is_invocable_r_v<double, F, double> // C++20 constraint option A // requires requires(F f, double x) { f(x) -> double; } // C++20 constraint option B - can be extracted into a concept double RootSolver::newton(double guess, double right_side, F func, double unc, int iter)
调用
std::function
时,以牺牲某些性能为代价使用它:double RootSolver::newton(double guess, double right_side, const std::function<double(double)>& func, double unc, int iter)
在这种情况下,您可以使用函数重载。
您可以在重载版本中传递函数名称和 x、a 和 b 作为参数,有点像这样(我现在只是在考虑 func、x、a 和 b,但你明白了):
1) 接受 func1 及其 2 个参数的重载版本 1
double newton(...<other parameters>..., double (*func)(double), double x)
2) 接受 func2 及其 3 个参数的重载版本 2
double newton(...<other parameters>..., double (*func)(double, double, double), double x, double a, double b)
现在,当您希望使用 func1 调用时,请使用:
newton(...., func1, x)
当您希望使用 func2 调用时,请使用:
newton(..., func2, x, a, b)
相关文章:
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 当从函数参数中的临时值调用复制构造函数时
- 如何从"decltype()"获取函数参数的数量<funtion>?
- 如何将lambda作为模板类的成员函数参数
- 模板参数推导失败,函数参数/参数不匹配
- 如何在C++中将迭代器作为函数参数传递
- 将函数参数"const char*"转换为"std::string_view"是
- C++ 如何将数组值解压缩为函数参数
- 主函数参数的属性
- 具有两个间接寻址运算符 (C++) 的函数参数的用途
- "Warning: Comma within array index expression"但逗号分隔函数参数
- 如何定义在用作函数参数时工作的类模板的转换
- 将函数参数完美转发到函数指针:按值传递呢?
- 为什么我不能将引用作为 std::async 的函数参数传递
- 什么..(省略号)作为函数原型中唯一的函数参数,C++?
- 是否可以就地构造一个固定大小的数组作为函数参数?
- 接受模板作为函数参数
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- Arduino 函数参数