These are some inputs and relative desired outputs
std::vector<std::string> v1{"aeiou", "bcdfghjk"};
std::vector<std::string> v2{"aeiou", "bcd"};
auto w1 = v1 | wanne_be_transpose;
auto w2 = v2 | wanne_be_transpose;
// w1 = {"ab","ec","id","of","ug","h","j","k"}
// w2 = {"ab","ec","id","o","u"}
Honestly I have no idea how to emulate it with ranges. (Even less in the general case of v1.size() > 2
, but my use case is inherently v1.size() == 2
, so I'd be ok with a solution only for this case.)
Initially I thought I could ranges::views::zip
together and then convert the pairs to inner ranges, but that wouldn't work, because zip
's output is as long as the shortest sequence.
Well, in Haskell there's Data.List.transpose
:
λ> Data.List.transpose $ ["aeiou","bcdfghjk"]
["ab","ec","id","of","ug","h","j","k"]
λ> Data.List.transpose $ ["aeiou","bcd"]
["ab","ec","id","o","u"]
Coming back to this question after some time, I think I can say that ranges::views::zip
or ranges::views::zip_with
couldn't be of help in implementing a general transpose
operation, because they take a variadiac number of arguments (so a number known at compile time), whereas transpose
would have to support a number of ranges know only at run time. The reason is explained in all 3 answers to this question.
Eric Niebler actually implemented the truncating version of this adaptor for his talk demonstrating range-v3 https://www.youtube.com/watch?v=mFUXNMfaciE.
But it didn't make it into range-v3 https://github.com/ericniebler/range-v3/issues/776
However, copy pasting from https://github.com/ericniebler/range-v3/blob/master/example/calendar.cpp we can just do
std::vector<std::string> v1{ "aeiou", "bcdfghjk" };
print2D(v1 | transpose());
https://godbolt.org/z/vj6bbsWso
To get the non-truncating version you could modify the copy pasted code.