Modern C++ In-Depth — Variadic Templates and Parameter Packs
In our previous installment, we looked at forwarding references and how they can be used to transparently pass arguments from one function call to another. This week, we’ll use that as a springboard to examine variadic templates and parameter packs.
Motivation
Last time, we introduced the example below to demonstrate how one might write a make_unique<T>
utility function:
namespace fds {
template <typename T, typename A>
std::unique_ptr<T> make_unique(A&& a)
{
return std::unique_ptr<T>(new T(std::forward<A>(a)));
}template <typename T, typename A, typename B>
std::unique_ptr<T> make_unique(A&& a, B&& b)
{
return std::unique_ptr<T>(new T(std::forward<A>(a), std::forward<B>(b)));
}
}
While this implementation is perfectly adequate when constructing a std::unique_ptr<T>
for a type that takes up to two arguments, it will not work if T
requires, say, five arguments. One way to address this issue would be to manually add even more overloads. But, is there a better way?
Variadic Templates and Parameter Packs
What if we could tell the compiler that it should expect to receive zero or more parameters (regardless of type), and that it should just pass all of those parameters to the constructor of our encapsulated type, T
?
With the introduction of C++11, we can do exactly that by using a variadic template.