我可以从 C++17 折叠表达式中解析出单个函数吗
Can I parse out individual functions from a C++17 fold expression
我正在尝试编写一个代码来求解耦合常微分方程(即 ODE)。该函数需要接受一个函数数组,每个函数都是耦合的 ODE 之一。我正在尝试使用 C++17 折叠表达式将函数传递给主函数,然后主函数将函数单独传递给求解器,一次一个。求解器需要求解方程,并根据结果修改输入地图。映射必须根据第一个函数的结果进行修改,因为修改后的映射是下一个函数的输入。通用代码如下所示。代码已简化以突出显示我正在尝试解决的问题。
int main()
{
ODESolver q;
std::map<std::string, double> inputs {
{"x", 1.0},
{"y", 2.0},
{"z", 3.0},
{"a", 4.0}
};
auto results = solver(inputs, func1, func2);
}
double func1(std::map<std::string, double> arr)
{
double dcadt = -arr["x"] * arr["y"] + arr["z"] * arr["a"];
return dcadt;
}
double func2(std::map<std::string, double> arr)
{
double dccdt = arr["x"] * arr["y"] - arr["a"] * arr["z"];
return dccdt;
}
此处显示class中的信息;
class ODESolver
{
public:
template<typename ...Funcs>
std::vector<double> framework(std::map<std::string, double> inputs, Funcs&&... funcs)
{
std::tuple<double, double> res;
for (int i = 0; i < funcs.size(); i++)
{
// - THIS IS WHERE MY PROBLEM IS MANIFESTED, THE
// COMPILER WILL NOT LET ME EXTRACT AN INDIVIDUAL
// FUNCTION FROM A FOLD EXPRESSION!
res = solver(inputs, funcs[i]);
step_size = std::get<1>(res);
inputs["x"] += 1.0;
inputs["y"] std::get<0>(res);
}
}
std::tuple<double, double>
ODESolver::solver(std::map<std::string, double>, const std::function<double(std::map<std::string, double>)& func)
{
double dydt = func(inputs);
double val = inputs["y"];
std::tuple<double, double> values(dydt, val);
return values;
}
};
上面的例子有些虚构,但它突出了我实际代码的问题。我不知道如何从 C++17 折叠表达式中提取单个函数,因此我可以将它们单独传递给另一个函数。从上面的代码可以看出,我需要先解决 func1
,这样它才能更新 inputs
映射,然后 func2
在其函数调用中使用 inputs
.有没有一种方法可以使用折叠表达式执行此操作,或者是否有另一种方法需要将函数从主程序传递给 framework
函数。
写一个 lambda 来做你需要做的事情:
auto apply_next = [&](auto&& f){
res = solver(inputs, f);
step_size = std::get<1>(res);
inputs["x"] += 1.0;
inputs["y"] += std::get<0>(res);
};
然后将 lambda 调用折叠到逗号上:
(apply_next(funcs), ...);
Expansion Statements 看起来正在为 C++20 走上正轨,这将允许您以更直接的方式开始编写:
for ... (auto&& f : funcs) {
res = solver(inputs, f);
step_size = std::get<1>(res);
inputs["x"] += 1.0;
inputs["y"] += std::get<0>(res);
}
您不使用常规 for 循环迭代 tuple/variadic 模板。
你可能会:
template<typename ...Funcs>
std::tuple<double, double> framework(std::map<std::string, double> inputs, Funcs&&... funcs)
{
std::tuple<double, double> res{};
auto l = [&](const auto& func){
res = solver(inputs, func);
step_size = std::get<1>(res);
inputs["x"] += 1.0;
inputs["y"] std::get<0>(res);
};
(l(funcs), ...);
return res;
}
我正在尝试编写一个代码来求解耦合常微分方程(即 ODE)。该函数需要接受一个函数数组,每个函数都是耦合的 ODE 之一。我正在尝试使用 C++17 折叠表达式将函数传递给主函数,然后主函数将函数单独传递给求解器,一次一个。求解器需要求解方程,并根据结果修改输入地图。映射必须根据第一个函数的结果进行修改,因为修改后的映射是下一个函数的输入。通用代码如下所示。代码已简化以突出显示我正在尝试解决的问题。
int main()
{
ODESolver q;
std::map<std::string, double> inputs {
{"x", 1.0},
{"y", 2.0},
{"z", 3.0},
{"a", 4.0}
};
auto results = solver(inputs, func1, func2);
}
double func1(std::map<std::string, double> arr)
{
double dcadt = -arr["x"] * arr["y"] + arr["z"] * arr["a"];
return dcadt;
}
double func2(std::map<std::string, double> arr)
{
double dccdt = arr["x"] * arr["y"] - arr["a"] * arr["z"];
return dccdt;
}
此处显示class中的信息;
class ODESolver
{
public:
template<typename ...Funcs>
std::vector<double> framework(std::map<std::string, double> inputs, Funcs&&... funcs)
{
std::tuple<double, double> res;
for (int i = 0; i < funcs.size(); i++)
{
// - THIS IS WHERE MY PROBLEM IS MANIFESTED, THE
// COMPILER WILL NOT LET ME EXTRACT AN INDIVIDUAL
// FUNCTION FROM A FOLD EXPRESSION!
res = solver(inputs, funcs[i]);
step_size = std::get<1>(res);
inputs["x"] += 1.0;
inputs["y"] std::get<0>(res);
}
}
std::tuple<double, double>
ODESolver::solver(std::map<std::string, double>, const std::function<double(std::map<std::string, double>)& func)
{
double dydt = func(inputs);
double val = inputs["y"];
std::tuple<double, double> values(dydt, val);
return values;
}
};
上面的例子有些虚构,但它突出了我实际代码的问题。我不知道如何从 C++17 折叠表达式中提取单个函数,因此我可以将它们单独传递给另一个函数。从上面的代码可以看出,我需要先解决 func1
,这样它才能更新 inputs
映射,然后 func2
在其函数调用中使用 inputs
.有没有一种方法可以使用折叠表达式执行此操作,或者是否有另一种方法需要将函数从主程序传递给 framework
函数。
写一个 lambda 来做你需要做的事情:
auto apply_next = [&](auto&& f){
res = solver(inputs, f);
step_size = std::get<1>(res);
inputs["x"] += 1.0;
inputs["y"] += std::get<0>(res);
};
然后将 lambda 调用折叠到逗号上:
(apply_next(funcs), ...);
Expansion Statements 看起来正在为 C++20 走上正轨,这将允许您以更直接的方式开始编写:
for ... (auto&& f : funcs) {
res = solver(inputs, f);
step_size = std::get<1>(res);
inputs["x"] += 1.0;
inputs["y"] += std::get<0>(res);
}
您不使用常规 for 循环迭代 tuple/variadic 模板。
你可能会:
template<typename ...Funcs>
std::tuple<double, double> framework(std::map<std::string, double> inputs, Funcs&&... funcs)
{
std::tuple<double, double> res{};
auto l = [&](const auto& func){
res = solver(inputs, func);
step_size = std::get<1>(res);
inputs["x"] += 1.0;
inputs["y"] std::get<0>(res);
};
(l(funcs), ...);
return res;
}