I am trying to understand below code. Copied directly from Jason Turner youtube video
#include <iostream>
#include <sstream>
#include <vector>
template<typename ...T>
std::vector<std::string> print(const T& ...t)
{
std::vector<std::string> retval;
std::stringstream ss;
(void)std::initializer_list<int>{
(
ss.str(""),
ss << t,
retval.push_back(ss.str()),
0)...
};
return retval;
}
int main()
{
for( const auto &s : print("Hello", "World", 5.4, 1.1, 2.2) ) {
std::cout << s << "\n";
}
}
Questions :
T
and t
are parameter packs.
There are two primary ways of using a pack: a fold expression (in C++17 and newer) and just a regular pack expansion.
A fold expression would look like this:
((ss.str(""), ss << t, retval.push_back(ss.str())), ...);
Fold expression repeats its operand for each pack element, inserting some operator (,
in this case) between parts belonging to each argument. The one above expands to:
((ss.str(""), ss << t1, retval.push_back(ss.str())), // <-- Inserted commas
(ss.str(""), ss << t2, retval.push_back(ss.str())), // <--
(ss.str(""), ss << t3, retval.push_back(ss.str())));
A regular expansion is similar, except that it always generates a comma, and that comma can not be an operator (as opposed to e.g. a separator between array initializers, or function arguments).
E.g. if you wrote (ss.str(""), ss << t, retval.push_back(ss.str()))...;
under the assumption that it would work like that fold expression, it wouldn't work, because the resulting comma would have to be an operator.
Because of this limitation, before C++17 people were using dummy arrays (or initializer_list
s like in your example). Here's how it would look with an array:
int dummy[] = {(ss.str(""), ss << t, retval.push_back(ss.str()), 0)...};
This expands to:
int dummy[] = {(ss.str(""), ss << t1, retval.push_back(ss.str()), 0),
(ss.str(""), ss << t2, retval.push_back(ss.str()), 0),
(ss.str(""), ss << t3, retval.push_back(ss.str()), 0)};
Here, the size of the array (or initializer_list
) matches the size of the pack.
,0
is necessary because each array element is an int
, so it must be initialized with an int
.