I recently ran across this puzzle, was finally able to struggle out a hacky answer (using index arrays), and wanted to share it (answer below). I am sure there are answers that use template recursion and answers that use boost; if you’re interested, please share other ways to do this. I think having these all in one place may benefit others and be useful for learning some of the cool C++11 template metaprogramming tricks.
Problem:
Given two tuples of equal length:
auto tup1 = std::make_tuple(1, 'b', -10);
auto tup2 = std::make_tuple(2.5, 2, std::string("even strings?!"));
How do you create a function that will “zip” the two tuples into a heterogeneous tuple of pairs?
std::tuple<
std::pair<int, double>,
std::pair<char, int>,
std::pair<int, std::string> > result =
tuple_zip( tup1, tup2 );
Where
std::get<0>(result) == std::make_pair(1, 2.5);
std::get<1>(result) == std::make_pair('b', 2);
std::get<2>(result) == std::make_pair(-10, std::string("even strings?!"));
First, a quick overview of index arrays:
And now to use our print_helper function:
Typing
seq<0,1,2>can be a bit of a pain, though. So we can use template recursion to create a class to generateseqs, so thatgens<3>::typeis the same asseq<0,1,2>:Since the
Ningens<N>::typewill always be the number of elements in the tuple, you can wrapprint_helperto make it easier:Note that the template arguments can be deduced automatically (typing all of that out would be a pain wouldn’t it?).
Now, the
tuple_zipfunction:As before, start with the helper function:
The code is a little tricky, particularly the trailing return type (the return type is declared as
autoand provided with->after the parameters are defined). This lets us avoid the problem of even defining what the return type will be, by simply declaring it returns the expression used in the function body (ifxandyareints,delctype(x+y)is resolved at compile time asint).Now wrap it in a function that provides the appropriate
seq<0, 1...N>usinggens<N>::type:Now you can use it as specified in the question:
And finally, if you provide a
<<operator forstd::pairyou can use the print function we defined above to print the zipped result:The output is:
Like
std::array,std::tupleis defined at compile time, and so it can be used to generate more optimizable code (more information is known at compile time compared to containers likestd::vectorandstd::list). So even though it’s sometimes a bit of work, you can sometimes use it to make fast and clever code. Happy hacking!Edit:
As requested, allowing tuples of different sizes and padding with null pointers:
And BTW, you’re going to need this now to use our handy
printfunction: