在不考虑远程调用的情况下,假设我们调用的是本地某个函数,为了支持参数的数量和类型可变,需要使用可变参模板,常见形式如下:
// 具体实现函数:利用C++17提供的折叠表达式来解析参数包
template<typename Tuple, std::size_t... Is>
void print_impl(const Tuple& t, std::index_sequence<Is...>)
{
std::initializer_list<int>{(std::cout << "value " << Is << " = " << std::get<Is>(t) << std::endl, 0)...};
}
C++11中的2种调用方式实现如下:
// 调用函数形式1
template<typename ...Args>
void print_args_1(const std::tuple<Args...> &tuple)
{
constexpr auto N = sizeof...(Args);
print_impl(tuple, std::make_index_sequence<N>{});
}
// 调用函数形式2
template<typename Tuple>
void print_args_2(const Tuple &tuple)
{
constexpr auto N = std::tuple_size<Tuple>::value;
print_impl(tuple, std::make_index_sequence<N>{});
}
上方2种调用方式都可以,第一种的template<typename ...Args>
更像是可变参模板,其通过sizeof...(Args)
获得参数数量,其返回值N必须由constexpr修饰以表示为编译期可求值常量;而第二种的template<typename Tuple>
虽然参数只有一个,但由于std::tuple本身就表示一个固定大小的异构值集合,可以有任意个成员数量,因此仍然算是一种可变参模板,其通过std::tuple_size<Tuple>::value
获得参数数量。
C++17中的2种调用方式实现如下:
// 调用函数形式1:通过变量模板std::index_sequence_for<Args...>简化代码
template<typename ...Args>
void print_args_1(const std::tuple<Args...> &tuple)
{
print_impl(tuple, std::index_sequence_for<Args...>{});
}
// 调用函数形式2:通过变量模板std::tuple_size_v<Tuple>简化代码
template<typename Tuple>
void print_args_2(const Tuple &tuple)
{
constexpr auto N = std::tuple_size_v<Tuple>;
print_impl(tuple, std::make_index_sequence<N>{});
}
函数使用例子如下:
int main()
{
print_args_1(std::make_tuple(1, 2.3, 'c'));
print_args_2(std::make_tuple(1, 2.3, 'c'));
system("pause");
return 0;
}