bkietz commented on code in PR #36393:
URL: https://github.com/apache/arrow/pull/36393#discussion_r1254383390
##########
cpp/src/arrow/util/range.h:
##########
@@ -151,5 +151,108 @@ LazyRange<Generator> MakeLazyRange(Generator&& gen,
int64_t length) {
return LazyRange<Generator>(std::forward<Generator>(gen), length);
}
-} // namespace internal
-} // namespace arrow
+/// \brief A helper for iterating multiple ranges simultaneously, similar to
C++23's
+/// zip() view adapter modelled after python's built-in zip() function.
+///
+/// \code {.cpp}
+/// const std::vector<SomeTable>& tables = ...
+/// std::function<std::vector<std::string>()> GetNames = ...
+/// for (auto [table, name] : Zip(tables, GetNames())) {
+/// static_assert(std::is_same_v<decltype(table), const SomeTable&>);
+/// static_assert(std::is_same_v<decltype(name), std::string&>);
+/// // temporaries (like this vector of strings) are kept alive for the
+/// // duration of a loop and are safely movable).
+/// RegisterTableWithName(std::move(name), &table);
+/// }
+/// \endcode
+///
+/// The zipped sequence ends as soon as any of its member ranges ends.
+///
+/// Always use `auto` for the loop's declaration; it will always be a tuple
+/// of references so for example using `const auto&` will compile but will
+/// *look* like forcing const-ness even though the members of the tuple are
+/// still mutable references.
+///
+/// NOTE: we *could* make Zip a more full fledged range and enable things like
+/// - gtest recognizing it as a container; it currently doesn't since Zip is
+/// always mutable so this breaks:
+/// EXPECT_THAT(Zip(std::vector{0}, std::vector{1}),
+/// ElementsAre(std::tuple{0, 1}));
+/// - letting it be random access when possible so we can do things like *sort*
+/// parallel ranges
+/// - ...
+///
+/// However doing this will increase the compile time overhead of using Zip as
+/// long as we're still using headers. Therefore until we can use c++20
modules:
+/// *don't* extend Zip.
+template <typename Ranges, typename Indices>
+struct Zip;
+
+template <typename... Ranges>
+Zip(Ranges&&...) -> Zip<std::tuple<Ranges...>,
std::index_sequence_for<Ranges...>>;
+
+template <typename... Ranges, size_t... I>
+struct Zip<std::tuple<Ranges...>, std::index_sequence<I...>> {
+ explicit Zip(Ranges... ranges) : ranges_(std::forward<Ranges>(ranges)...) {}
+
+ std::tuple<Ranges...> ranges_;
+
+ using sentinel = std::tuple<decltype(std::end(std::get<I>(ranges_)))...>;
+ constexpr sentinel end() { return {std::end(std::get<I>(ranges_))...}; }
+
+ struct iterator : std::tuple<decltype(std::begin(std::get<I>(ranges_)))...> {
+ using std::tuple<decltype(std::begin(std::get<I>(ranges_)))...>::tuple;
+
+ constexpr auto operator*() {
+ return
std::tuple<decltype(*std::get<I>(*this))...>{*std::get<I>(*this)...};
+ }
+
+ constexpr iterator& operator++() {
+ (++std::get<I>(*this), ...);
+ return *this;
+ }
+
+ constexpr bool operator!=(const sentinel& s) const {
+ bool all_iterators_valid = (... && (std::get<I>(*this) !=
std::get<I>(s)));
+ return all_iterators_valid;
+ }
+ };
+ constexpr iterator begin() { return {std::begin(std::get<I>(ranges_))...}; }
+};
+
+/// \brief A lazy sequence of integers which starts from 0 and never stops.
+///
+/// This can be used in conjunction with Zip() to emulate python's built-in
+/// enumerate() function:
+///
+/// \code {.cpp}
+/// const std::vector<SomeTable>& tables = ...
+/// for (auto [i, table] : Zip(Enumerate<>, tables)) {
Review Comment:
Yes, I opted for the simplest option. It'll be easy to add support for an
arbitrary start index later if needed.
Related: one thing that unfortunately can't be done with structured bindings
is nested unpacking, like
```
for (auto [ [i, table], name ] : Zip(Enumerate(tables), names)) {}
```
which is why I opted to make it strictly a sibling sequence for Zip
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]