这是一个打印参数的可变参数模板。
#include <string>
#include <iostream>
void Output() {
std::cout<<std::endl;
}
template<typename First, typename ... Strings>
void Output(First arg, const Strings&... rest) {
std::cout<<arg<<" ";
Output(rest...);
}
int main() {
Output("I","am","a","sentence");
Output("Let's","try",1,"or",2,"digits");
Output(); //<- I do not want this to compile, but it does.
return 0;
}
有没有办法在没有“无参数”调用的情况下获得此功能,并且每次都不必编写两个函数?
答案 0 :(得分:3)
您可能希望保留第一个参数和其余参数的分离,您可以使用:
template<typename First, typename ... Rest>
void Output(First&& first, Rest&&... rest) {
std::cout << std::forward<First>(first);
int sink[]{(std::cout<<" "<<std::forward<Rest>(rest),0)... };
(void)sink; // silence "unused variable" warning
std::cout << std::endl;
}
请注意,我使用完美转发来避免复制任何参数。以上内容具有避免递归的额外好处,因此可能产生更好(更快)的代码。
我写sink
的方式也保证从rest
扩展的表达式从左到右进行评估 - 与仅仅编写辅助函数的天真方法相比,这很重要{{1 }}
答案 1 :(得分:2)
从转发类型函数调用该函数,并具有如下的static_assert:
template <typename ... Args>
void forwarder(Args ... args) {
static_assert(sizeof...(args),"too small");
Output(args...);
}
答案 2 :(得分:2)
据我所知,有两个任务:
Output()
来电。我对第1项的解决方案如下:
template<typename T>
void Output(const T & string) {
std::cout<<string<<std::endl;
}
template<typename First, typename ... Strings>
void Output(const First & arg, const Strings & ... rest) {
std::cout<<arg<<" ";
Output(rest...);
}
基本上,当模板列表为空时,不是结束递归,而是在它只包含一种类型时结束它。上述问题与代码之间存在一个区别:如果在最后一项之后没有输出任何空格。相反,它只输出换行符。
对于第二个问题,请参阅Daniel Frey的回答。我真的很喜欢这个解决方案,虽然花了一些时间来掌握它(我赞成了答案)。与此同时,我发现它使代码更难以阅读/理解,因此难以维护。目前我不会在任何小型个人代码片段中使用该解决方案。