使用任意数量的参数生成对lambdas的调用

lrl*_*eon 7 template-meta-programming variadic-templates generic-lambda fold-expression c++17

事实证明,以下定义对我非常有用:

template<class Func, class... Args>
void apply_on_each_args(Func f, Args... args)
{
    (f(args), ...);
}
Run Code Online (Sandbox Code Playgroud)

基本上,在逗号运算符上折叠的参数包允许定义对带参数的函数的多个调用.例如:

apply_on_each_args([] (auto x) { cout << x << endl; }, 1, 2, "hello");
Run Code Online (Sandbox Code Playgroud)

将打电话给匿名lambda 1,2"hello".

提出这个想法,我想做同样的事情,但传递lambdas采取两个,三个等参数.例如,类似的东西

apply_on_each_args([] (auto x, auto y) { /* use x and y */ }, 1, 2, "hello",  "bye");
Run Code Online (Sandbox Code Playgroud)

任何能够实现它的线索,技术,想法等?

bol*_*lov 3

好吧,今晚我的巫术很强大:

\n\n
auto foo(int, int) -> void;\n\ntemplate <class Func, class... Args, std::size_t... I>\nvoid apply_on_2x_indexes(Func f,  std::index_sequence<I...>, std::tuple<Args...> t)\n{\n    (f(std::get<I * 2>(t), std::get<I * 2 + 1>(t)), ...);\n}\n\ntemplate<class Func, class... Args>\nvoid apply_on_each_2_args(Func f, Args... args)\n{\n    apply_on_2x_indexes(f, std::make_index_sequence<sizeof...(Args) / 2>{},\n                        std::tuple{args...});   \n}\n\nauto test()\n{\n    apply_on_each_2_args(foo, 1, 2, 3, 4); // calls foo(1, 2) foo(3, 4)\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

为简洁起见,省略转发。

\n\n

为了更好地理解它是如何工作的,我们可以手动扩展:

\n\n
apply(on_each_2_args(foo, 1, 2, 3, 4))\n\xe2\x86\xb3 apply_on_2x_indexes(f, std::index_sequence<0, 1>{}, std::tuple{1, 2, 3, 4})\n  \xe2\x86\xb3 (f(std::get<0 * 2>(t), std::get<0 * 2 + 1>(t)),  f(std::get<1 * 2>(t), std::get<1 * 2 + 1>(t)))\n    (f(std::get<0>(t), std::get<1>(t)),  f(std::get<2>(t), std::get<3>(t)))\n    (f(1, 2), f(3, 4))\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

另一种方法:

\n\n

我不喜欢你的调用语法中的一件事

\n\n
apply_on_each_2_args([] (auto x, auto y) { }, 1, 2, "hello",  "bye");\n
Run Code Online (Sandbox Code Playgroud)\n\n

不清楚每次调用的参数如何分组。

\n\n

所以我想把它们分组。不幸的是,我无法让它像这样的可变参数工作:

\n\n
apply_on_each_2_args([] (auto x, auto y) { }, {1, 2}, {"hello",  "bye"});\n
Run Code Online (Sandbox Code Playgroud)\n\n

但我们可以更详细一点tuple

\n\n
template<class Func, class... Args>\nvoid apply_on_each_2_args(Func f, Args... args)\n{\n    (std::apply(f, args), ...);\n}\n\nauto test()\n{\n    apply_on_each_2_args([](auto a, auto b){ /*use a, b*/ },\n                         std::tuple{1, 2}, std::tuple{"hello", "bye"});\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

不完全是您所要求的,但这是一种值得考虑的方法。

\n

  • 如果模板函数采用 std::initializer_list&lt;T&gt; 参数,则 `(func, {1, 2}, {"hello", "bye"})` 语法可以工作,但不幸的是,这意味着每个组中的所有参数需要具有相同的类型。 (2认同)