C++-11 implementation of std::ranges::zip_view and std::ranges::views::zip
- Looping over multiple containers of different types:
#include "zip_view.hpp" #include <array> #include <cstddef> #include <deque> #include <forward_list> #include <initializer_list> #include <iostream> #include <list> #include <string> #include <tuple> #include <vector> template <typename Tuple, std::size_t... Is> void print_tuple_impl(Tuple const& tuple, gst::detail::index_sequence<Is...>) { static_cast<void>(std::initializer_list<int>{(std::cout << std::get<Is>(tuple) << ' ', 0)...}); std::cout << '\n'; } // Main function to print the tuple template <typename... Args> void print_tuple(std::tuple<Args...> const& tuple) { print_tuple_impl(tuple, gst::detail::make_index_sequence<sizeof...(Args)>{}); } int main() { std::array<int, 3> a_3 = {1, 2, 3}; std::list<double> l_5 = {1.1, 2.2, 3.3, 4.4, 5.5}; std::deque<bool> d_7 = {true, false, true, false, true, false, true}; std::forward_list<char> f_6 = {'a', 'b', 'c', 'd', 'e', 'f'}; std::vector<std::string> v_4 = {"one", "two", "three", "four"}; for (auto const iter_tuple : gst::ranges::views::zip(a_3, l_5, d_7, f_6, v_4)) { print_tuple(iter_tuple); } // 1 1.1 1 a one // 2 2.2 0 b two // 3 3.3 1 c three }
- When all containers are random-access, you can use
std::sortdirectly on the zipped view:#include "zip_view.hpp" #include <algorithm> #include <vector> int main() { std::vector<int> keys = {3, 1, 2}; std::vector<double> values = {30.0, 10.0, 20.0}; auto zipped = gst::ranges::views::zip(keys, values); std::sort(zipped.begin(), zipped.end(), [](auto const& a, auto const& b) { return std::get<0>(a) < std::get<0>(b); }); // keys: {1, 2, 3} // values: {10.0, 20.0, 30.0} }
- When a
std::listorstd::forward_listis involved,std::sortcannot be used on the view because the iterator category is no longer random-access. In such cases, consider using index-based sorting or materializing the data.
- C++-11 for the examples
- C++-23 for the tests (
Catch2) - C++-23 for the benchmarks (for comparing to
std::ranges::zip_view)
mkdir build
cd build
cmake ..
makegst::ranges::zip_view adapts its iterator category to the weakest underlying range, similar to std::ranges::zip_view:
- Random Access Iterator: When all underlying ranges are random-access (e.g.,
std::vector,std::array,std::deque) - Bidirectional Iterator: When all underlying ranges are at least bidirectional (e.g.,
std::list) - Forward Iterator: When any underlying range is only forward (e.g.,
std::forward_list)
This allows algorithms like std::sort to work directly on the zipped view when all underlying ranges support random access.
The project includes comprehensive benchmarks comparing gst::ranges::views::zip with std::ranges::views::zip (C++23):
View the benchmark history dashboard to track performance over time.
cd build
./benchmarks/ZipViewBenchmark