多个可变参数模板函数

Multiple variadic templates function

假设我有两个函数 f1()f2() 定义如下:

template<class ... Types> void f1(Types ... args1)
template<class ... Types> void f2(Types ... args2)

现在我想创建第三个函数 f3(),它接受输入 f1()f2(),我如何定义 f3()args1...args2...?

template<class F1, class F2> void f3(F1 f1, F2 f2) {
  f1();  // how do I call f1? I need to pass in the args... 
}    

你不能。

因为模板函数是一组函数。你可以传递一个函数,解释模板类型,

f3(f1<int, long, long>, f2<char, int>);

而不是全套功能。

我能建议的最好的办法是将模板函数包装在结构中

struct s1
 {
   template <typename ... Types>
   static void f1 (Types ... args1)
    { }
 };

struct s2
 {
   template <typename ... Types>
   static void f2 (Types ... args2)
    { }
 };

所以你可以传递给 f3() s1s2 对象

s1  a;
s2  b;

f3(a, b);

或者只是类型

f3<s1, s2>();

正如 Jarod42 所建议的,您还可以将 f1()f2() 包装在几个 lambda 表达式中(仅来自 C++14)

auto l1 = [](auto&& ... args) { f1(std::forward<decltype(args)>(args)...); };
auto l2 = [](auto&& ... args) { f2(std::forward<decltype(args)>(args)...); };

f3(l1, l2)

what I mean is when I call f3, I offer f1 and f2. I also need to pass in the params for f1 and f2. How do I do that?

但是f1()f2()的参数是一样的吗? 还是两个不同的集合?

在第一种情况下,您可以将它们作为模板可变参数传递;类似于(根据 Jarod42 的建议)

template <typename L1, typename L2, typename ... Args>
void f3 (L1 l1, L2 l2, Args const & ... as)
 {
   L1(as...);
   L2(as...);
 }  

auto l1 = [](auto&& ... args) { f1(std::forward<decltype(args)>(args)...); };
auto l2 = [](auto&& ... args) { f2(std::forward<decltype(args)>(args)...); };

f3(l1, l2, 1, '2', 3L, 4ULL);

如果您需要两组不同的参数,您需要将参数包装在 std::tuple 或类似的东西中。

template <typename L1, typename L2, typename ... As1, typename ... As2>
void f3 (L1 l1, L2 l2, std::tuple<As1...> const & t1, std::tuple<As2...> const & t2)
 {
   std::apply(l1, t1);
   std::apply(l2, t2);
 }  

auto l1 = [](auto&& ... args) { f1(std::forward<decltype(args)>(args)...); };
auto l2 = [](auto&& ... args) { f2(std::forward<decltype(args)>(args)...); };

f3(l1, l2, std::make_tuple(1, 2l, '3'), std::make_tuple('4', 5ull));

但请注意 std::apply() 仅适用于 C++17:从元组中提取参数之前稍微复杂一些。

how do I do that without c++17?

以下是使用 std::index_sequence_forstd::index_sequence

解压元组的完整 C++14 示例
#include <tuple>
#include <iostream>
#include <type_traits>

template <typename ... Ts>
void f1 (Ts ... as)
 { std::cout << "- f1: " << sizeof...(Ts) << " arguments" << std::endl; }

template <typename ... Ts>
void f2 (Ts ... as)
 { std::cout << "- f2: " << sizeof...(Ts) << " arguments" << std::endl; }

template <typename L, typename ... Ts, std::size_t ... Is>
void f3_helper (L l, std::tuple<Ts...> const & t, std::index_sequence<Is...>)
 { l(std::get<Is>(t)...); }

template <typename L1, typename L2, typename ... As1, typename ... As2>
void f3 (L1 l1, L2 l2, std::tuple<As1...> const & t1,
         std::tuple<As2...> const & t2)
 {
   f3_helper(l1, t1, std::index_sequence_for<As1...>{});
   f3_helper(l2, t2, std::index_sequence_for<As2...>{});
 }  

int main()
 {
   auto l1 = [](auto && ... args)
    { f1(std::forward<decltype(args)>(args)...); };

   auto l2 = [](auto && ... args)
    { f2(std::forward<decltype(args)>(args)...); };

   f3(l1, l2, std::make_tuple(1, 2l, '3'), std::make_tuple('4', 5ull));
 }