使用每个参数调用函数
Invoke function with each argument
我想调用一个函数,每个参数都作为参数包传递。
我已经写了一个简单的模板函数:
template<class Function, class... Args>
auto for_each_arg(Function f, Args&&... args) {
(f(std::forward<Args>(args)), ...);
}
当我将它与仅接受一个参数的函数一起使用时,它工作正常:
void foo(int a) { }
for_each_arg(foo, 1);
但是当我尝试调用一个带有两个或更多参数的函数时:
void bar(int a, int b) { }
for_each_arg(bar, 1, 2);
它给出一个错误too few arguments for call
。我该如何解决?可以在 C++17 中创建解决方案。
void bar(int a, int b) { }
for_each_arg(
[](auto&&tup){
return std::apply(bar, decltype(tup)(tup));
}
)(std::make_tuple(1, 2));
这里调用者将参数打包成元组,我们将它们解包到调用中。这使得参数的包装很清楚。
我们可以将 apply 调用移到 foreach 函数中。理论上,我们 csn 检测目标是否接受 1 个参数,如果不接受,则将参数解压为元组,但我建议不要这样做。像这样乱七八糟的操作,很多事情都出问题了。
apply_foreach(f, tuples...)
是一个简洁且易于指定的函数。
古老的递归方式很简单
#include <iostream>
template <typename F>
void invoke_two_args (F)
{ }
template <typename F, typename A0, typename A1, typename ... Args>
void invoke_two_args (F f, A0 && a0, A1 && a1, Args && ... args)
{
f(std::forward<A0>(a0), std::forward<A1>(a1));
invoke_two_args(f, std::forward<Args>(args)...);
}
void bar(int a, int b)
{ std::cout << "bar: " << a << ' ' << b << '\n'; }
int main ()
{
// compile
invoke_two_args(bar, 2, 3, 5, 7, 11, 13);
// compilation error: wrong number of arguments
// invoke_two_args(bar, 2, 3, 5, 7, 11, 13, 17);
}
只有当参数列表不太长时,这是一个很好的解决方案。
你可以这样使用:
template <typename F, typename... Args>
auto curry(F&& f, Args&&... args) {
if constexpr (std::is_invocable_v<F, Args...>) {
return std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
} else {
return [&](auto&&... more_args) {
return curry(std::forward<F>(f), std::forward<Args>(args)..., more_args...);
};
}
}
int foo(int a, int b) { return a + b; }
// usage
auto func = curry(foo);
func(1)(2);
我想调用一个函数,每个参数都作为参数包传递。 我已经写了一个简单的模板函数:
template<class Function, class... Args>
auto for_each_arg(Function f, Args&&... args) {
(f(std::forward<Args>(args)), ...);
}
当我将它与仅接受一个参数的函数一起使用时,它工作正常:
void foo(int a) { }
for_each_arg(foo, 1);
但是当我尝试调用一个带有两个或更多参数的函数时:
void bar(int a, int b) { }
for_each_arg(bar, 1, 2);
它给出一个错误too few arguments for call
。我该如何解决?可以在 C++17 中创建解决方案。
void bar(int a, int b) { }
for_each_arg(
[](auto&&tup){
return std::apply(bar, decltype(tup)(tup));
}
)(std::make_tuple(1, 2));
这里调用者将参数打包成元组,我们将它们解包到调用中。这使得参数的包装很清楚。
我们可以将 apply 调用移到 foreach 函数中。理论上,我们 csn 检测目标是否接受 1 个参数,如果不接受,则将参数解压为元组,但我建议不要这样做。像这样乱七八糟的操作,很多事情都出问题了。
apply_foreach(f, tuples...)
是一个简洁且易于指定的函数。
古老的递归方式很简单
#include <iostream>
template <typename F>
void invoke_two_args (F)
{ }
template <typename F, typename A0, typename A1, typename ... Args>
void invoke_two_args (F f, A0 && a0, A1 && a1, Args && ... args)
{
f(std::forward<A0>(a0), std::forward<A1>(a1));
invoke_two_args(f, std::forward<Args>(args)...);
}
void bar(int a, int b)
{ std::cout << "bar: " << a << ' ' << b << '\n'; }
int main ()
{
// compile
invoke_two_args(bar, 2, 3, 5, 7, 11, 13);
// compilation error: wrong number of arguments
// invoke_two_args(bar, 2, 3, 5, 7, 11, 13, 17);
}
只有当参数列表不太长时,这是一个很好的解决方案。
你可以这样使用:
template <typename F, typename... Args>
auto curry(F&& f, Args&&... args) {
if constexpr (std::is_invocable_v<F, Args...>) {
return std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
} else {
return [&](auto&&... more_args) {
return curry(std::forward<F>(f), std::forward<Args>(args)..., more_args...);
};
}
}
int foo(int a, int b) { return a + b; }
// usage
auto func = curry(foo);
func(1)(2);