I am trying to learn C++20/C++23 features and am stuck on the following problem. Suppose there are two vectors of arrays of the same size:
std::vector<std::array<int, 2>> v1 = { {1, 2}, {3, 4}, {5, 6} };
std::vector<std::array<int, 2>> v2 = { {7, 8}, {9, 10}, {11, 12} };
I would like to create a view that would be a double zip application to these vectors: first to the vectors themselves, and then to the elements of the resulting view.
For the two vectors above, the resulting view will look something like this:
[[(1, 7), (2, 8)], [(3, 9), (4, 10)], [(5, 11), (6, 12)]]
Also, I would like to be able to apply ranges algorithm (sort, unique, etc.) to it as well, i.e. the view elements have to be swappable.
I have tried the following:
auto result = std::ranges::views::zip(v1, v2)
| std::ranges::views::transform([](const auto& arrays) {
return std::ranges::views::zip(std::get<0>(arrays), std::get<1>(arrays));
});
This gives the correct result, but the resulting view can only be read from, but not processed by algorithms.
What is the most suitable way to solve this problem using the modern C++20 (23) ranges library?
An expanded example of what I'm trying to do, since there are questions in the comments.
Suppose there are two vectors:
std::vector<std::array<int, 3>> v1 = { {4, 5, 6}, {1, 2, 3}, {5, 6, 4} };
std::vector<std::array<int, 3>> v2 = { {15, 14, 13}, {12, 10, 11}, {12, 10, 11} };
I want to zip these two vectors to get a view that looks like this:
[[(4, 15), (5, 14), (6, 13)], [(1, 12), (2, 10), (3, 11)], [(5, 12), (6, 10), (4, 11)]]
With my approach above, I can get this and print it out. I can even swap the elements of the array, but I can't swap the arrays themselves. Here's what I mean.
First, I want to process this view with:
auto get_first = [](const auto& p)
{
return std::get<0>(p);
};
std::ranges::for_each(view, [&get_first](auto a)
{
std::ranges::rotate(a, std::ranges::max_element(a, std::ranges::less{}, get_first));
});
To get such view:
[[(6, 13), (4, 15), (5, 14)], [(3, 11), (1, 12), (2, 10)], [(6, 10), (4, 11), (5, 12)]]
And that will work.
Second, I want to sort this view to remove duplicates in the future:
using namespace std::placeholders;
auto lex_less = std::bind(std::ranges::lexicographical_compare, _1, _2, std::ranges::less{}, get_first, get_first);
std::ranges::sort(result, lex_less);
That should lead to this view:
[[(3, 11), (1, 12), (2, 10)], [(6, 13), (4, 15), (5, 14)], [(6, 10), (4, 11), (5, 12)]]
And, as a result, v1 and v2 would be:
v1: [[3, 1, 2], [6, 4, 5], [6, 4, 5]]
v2: [[11, 12, 10], [13, 15, 14], [10, 11, 12]]
But it won't work, because the iterators of the resulting transform view are not swappable (and it looks like they don't have to be). So I'm looking for a way to get something similar using other approaches. Since I am learning modern C++, I would like to know if it is possible to achieve the described behavior with it.