Writing functions that can take an arbitrary number of parameters seems almost like a fantasy right? But guess what, with C++11 we now have Variadic Templates which can easily perform this task for us. What makes Variadic Templates interesting, is that it’s a combination of several other concepts like Function Overloading, Recursion and Templates.
It basically works by passing in what we call a “Variadic Argument”, which is similar to a dynamic array that stores all the arguments. We can perform all kinds of operations on this Variadic Parameter as you’ll see later in this tutorial.
C++ Variadic Templates Examples
We’ll take a look at two common examples of where Variadic templates might be used.
Example# 1
In this example we are going to make an arbitrary print()
function, that accepts any number of parameters and prints them all out on screen. The best part of the above code, is that it’s templated, so it can accept any type of data.
#include <iostream>
using namespace std;
void print() {
cout << "empty" << endl;
}
template <typename T, typename... Args>
void print(T first, Args... args) {
cout << first << endl;
print(args...);
}
int main() {
print(1,2,3,4,5);
}
1
2
3
4
5
empty
On a side note, you don’t have to print anything in the parameter-less print()
function. We just included it for illustrative purposes.
Here is a breakdown of what’s really happening behind the scenes.
print(1, 2, 3, 4, 5) // firstArg == 1
// ...args == {2,3,4,5}
print(2, 3, 4, 5) // firstArg == 2
// ...args == {3,4,5}
print(3, 4, 5) // firstArg == 3
// ...args == {4,5}
print(4, 5) // firstArg == 4
// ...args == {5}
print(5) // firstArg == 5
// ...args == {}
print()
The reason we need a print() function without any parameters is evident from the above process-breakdown. Once we reach the second last call, since args is now empty, print()
will be called without any parameters. If a function does not exist which can handle this call, an error will be thrown. Hence we make an empty placeholder of sorts.
If you didn’t already know, this is the concept overloaded functions in C++, where we have multiple functions with the same name, but the one that get’s called is determined by the number and type of parameters in the function call.
Example# 2
Here is another interesting example, where we have an arbitrary number of arguments, which are all added together and the result is returned.
#include <iostream>
using namespace std;
template<typename T>
T add(T last) {
return last;
}
template <typename T, typename... Args>
T add(T first, Args... args) {
return first + add(args...);
}
int main() {
cout << add(1,2,3,4,5);
}
15
We need to change up one or two things this time, due to the nature of the operation we are performing.
For one, that last call in the process is no longer a parameter-less call, rather it’s a call with just a single parameter. And since it’s a single number, we can’t add it with anything, so we stop the calling right there.
The main add()
function in the above example uses some fairly standard recursive code. The return values of all the add()
functions are added together and returned back to the main()
function where the value is printed out.
This marks the end of the C++ Variadic Templates Tutorial. Any suggestions or contributions for CodersLegacy are more than welcome. Questions regarding the tutorial content can be asked in the comments section below.