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_lists 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With