Use Range-v3:
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/transform.hpp>
#include <range/v3/view/chunk.hpp>
using namespace ranges;
using namespace ranges::views;
int main() {
std::vector<int> origin {1, 2, 3, 4, 5, 6, 7, 8};
std::vector<std::pair<int, int>> goal {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
auto constexpr makePairFromRangeOf2 = [](auto two){
return std::make_pair(two.front(), two.back());
};
auto result = origin | chunk(2)
| transform(makePairFromRangeOf2)
| to_vector;
}
Notice that if you only have to loop on result
, then you only need it to be a range, so you can leave | to_vector
out, because you'll still be able to do result.begin()
and result.end()
, which is what makes result
a range.
If you don't need the inner containers to truly be std::pair
s, but your just happy with calling, say, result.front().front()
instead of result.front().first
, then you can leave also the transform
, and just be happy with auto result = origin | chunk(2);
.
You don't mention why you only want a standard solution. However consider that <ranges>
is standard in C++20. Unfortunately that feature is not as powerful as pre-C++20 Range-v3 library. But it will be at some point (C++23?), I think without any doubts.
origin
always contains an even amount of elements – Xenonfor
loop does the trick. Why making things complicated (as proposed answers are) when they can be so simple ? – Blossom