It is straight forward to write a function with variadic templates, that accept an arbitrary number of arguments. The only difference to the general pattern is, that a concrete type is used as first argument (head) - instead of a template parameter. The following example shows a function foobar
, that accepts an arbitrary number of strings.
// used for end of recursion - and for the empty arguments list
void foobar() { }
template <typename ...Tail>
void foobar(const std::string& head, Tail&&... tail)
{
// do something with head
std::cout << head << '
';
// call foobar recursively with remaining arguments
foobar(std::forward<Tail>(tail)...);
}
foobar("Hello", "World", "...");
Personally, I prefer using std::initializer_list
instead of variadic templates. Because variadic templates are more complex and require additional experience. With std::initializer_list
, it might look like this:
void foobar(std::initializer_list<std::string> values)
{
for (auto& value : values) {
// do something with value
std::cout << value << '
';
}
}
foobar({ "Hello", "World", "...", });
Unfortunately, the additional curly braces are required when using std::initializer_list
with regular functions. They are not required for constructors, if the new initializer syntax is used.
Edit: Rewrote the answer according to the feedback. In particular I have changed the order of the two solutions/examples.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…