介绍几种常用的变长参数解包的方法:
- 递归解包
template<typename Arg>
void print1(const Arg& arg){
std::cout<<arg<<std::endl;
}
template<typename Arg,typename ...Args>
void print1(const Arg& arg,const Args& ...args){
std::cout<<arg<<" ";
print1(args...);
}
print1("test1",18,3.14,std::string("test2"));
- 根据参数个数大于0解包
template<typename Arg,typename ...Args>
void print2(const Arg& arg,const Args& ...args){
if constexpr(sizeof...(args) > 0){
std::cout<<arg<<" ";
print2(args...);
}
}
- 使用逗号表达式与std::initializer_list解包
template<typename ...Args>
void print3(const Args& ...args){
(void)std::initializer_list<int>{([&args]{std::cout<<args<<" ";}(),0)...};
std::cout<<std::endl;
}
第三种解包方式配合C++17std::index_sequence与std::make_index_sequence可以很方便优雅地实现std::tuple的遍历:
template<typename T,std::size_t ...N>
void printTuple(const T& t,std::index_sequence<N...>){
(void)std::initializer_list<int>{([&t](){
std::cout<<std::get<N>(t)<<" ";
}(),0)...};
std::cout<<std::endl;
}
template<typename T>
void print(const T& t){
constexpr auto size = std::tuple_size_v<T>;
printTuple(t,std::make_index_sequence<size>());
}
auto t = std::make_tuple(1,2,3,"Naruto");
print(t);
这个部分展开如下:
(&t{std::cout<<std::get<0>(t)<<" “;}(),0), &t{std::cout<<std::get<1>(t)<<” “;}(),0),0), &t{std::cout<<std::get<2>(t)<<” ";}(),0), etc… )
逗号表达式从左至右求解表达式,结果为最后一个表达式的返回值,故匿名std::initializer_list中的值都为0。