|
|
@@ -3,80 +3,71 @@
|
|
|
#include <iterator>
|
|
|
#include <tuple>
|
|
|
|
|
|
-#include "proxy.h"
|
|
|
-
|
|
|
-namespace iterator::zip {
|
|
|
- template <typename... Iters> struct impl {
|
|
|
- public:
|
|
|
- using difference_type = std::common_type_t<
|
|
|
- typename std::iterator_traits<Iters>::difference_type...>;
|
|
|
-
|
|
|
- public:
|
|
|
- std::tuple<Iters...> data;
|
|
|
-
|
|
|
- public:
|
|
|
- impl() = default;
|
|
|
- impl(Iters &&... iters) : data(iters...) {}
|
|
|
-
|
|
|
- auto operator*() const {
|
|
|
- return std::make_tuple(*std::get<Iters>(data)...);
|
|
|
- }
|
|
|
-
|
|
|
- void operator++(int) {
|
|
|
- [[maybe_unused]] auto l = {(++(std::get<Iters>(data)), 0)...};
|
|
|
- }
|
|
|
-
|
|
|
- void operator--(int) {
|
|
|
- [[maybe_unused]] auto l = {(--(std::get<Iters>(data)), 0)...};
|
|
|
- }
|
|
|
-
|
|
|
- void operator+=(difference_type d) {
|
|
|
- [[maybe_unused]] auto l = {((std::get<Iters>(data) += d), 0)...};
|
|
|
- }
|
|
|
-
|
|
|
- bool operator==(impl const & other) const { return data == other.data; }
|
|
|
-
|
|
|
- auto operator-(impl const & other) const {
|
|
|
- return std::get<0>(data) - std::get<0>(other.data);
|
|
|
- }
|
|
|
- };
|
|
|
-}
|
|
|
-
|
|
|
-namespace std {
|
|
|
- template <typename... Iters>
|
|
|
- struct iterator_traits<::iterator::zip::impl<Iters...>> {
|
|
|
- using difference_type =
|
|
|
- common_type_t<typename iterator_traits<Iters>::difference_type...>;
|
|
|
- using iterator_category =
|
|
|
- common_type_t<typename iterator_traits<Iters>::iterator_category...>;
|
|
|
- };
|
|
|
+#include "facade.h"
|
|
|
+
|
|
|
+namespace iterator::detail {
|
|
|
+template <typename Tuple, typename IS> class zip_iterator_impl;
|
|
|
+
|
|
|
+template <typename... Ts, size_t... Is>
|
|
|
+class zip_iterator_impl<std::tuple<Ts...>, std::index_sequence<Is...>> {
|
|
|
+public:
|
|
|
+ using difference_type =
|
|
|
+ std::common_type_t<typename std::iterator_traits<Ts>::difference_type...>;
|
|
|
+
|
|
|
+public:
|
|
|
+ zip_iterator_impl() = default;
|
|
|
+ zip_iterator_impl(Ts... iters) : _data(iters...) {}
|
|
|
+
|
|
|
+ auto dereference() const {
|
|
|
+ return std::forward_as_tuple(*std::get<Is>(_data)...);
|
|
|
+ }
|
|
|
+
|
|
|
+ void increment() {
|
|
|
+ [[maybe_unused]] auto l = {((++std::get<Is>(_data)), 0)...};
|
|
|
+ }
|
|
|
+ void decrement() {
|
|
|
+ [[maybe_unused]] auto l = {((++std::get<Is>(_data)), 0)...};
|
|
|
+ }
|
|
|
+ void advance(difference_type d) {
|
|
|
+ [[maybe_unused]] auto l = {((std::get<Is>(_data) += d), 0)...};
|
|
|
+ }
|
|
|
+
|
|
|
+ bool equal_to(zip_iterator_impl const & other) const { return _data == other._data; }
|
|
|
+
|
|
|
+ auto distance_to(zip_iterator_impl const & other) const {
|
|
|
+ return std::get<0>(other._data) - std::get<0>(_data);
|
|
|
+ }
|
|
|
+
|
|
|
+private:
|
|
|
+ std::tuple<Ts...> _data;
|
|
|
+};
|
|
|
}
|
|
|
|
|
|
namespace iterator {
|
|
|
- template <typename... Iters>
|
|
|
- class zip_iterator
|
|
|
- : public proxy<zip::impl<Iters...>, zip_iterator<Iters...>> {
|
|
|
- private:
|
|
|
- using super = proxy<zip::impl<Iters...>, zip_iterator<Iters...>>;
|
|
|
+ template <typename... Ts>
|
|
|
+ using index_sequence = decltype(std::make_index_sequence<sizeof...(Ts)>{});
|
|
|
+ template <typename... Ts>
|
|
|
+ using zip_impl = detail::zip_iterator_impl<std::tuple<Ts...>, index_sequence<Ts...>>;
|
|
|
|
|
|
+ template <typename... Iters>
|
|
|
+ class zip_iterator : public zip_impl<Iters...>, public facade<zip_iterator<Iters...>> {
|
|
|
public:
|
|
|
zip_iterator() = default;
|
|
|
- zip_iterator(Iters &&... iters) : super(std::forward<Iters>(iters)...) {}
|
|
|
+ zip_iterator(Iters... iters) : zip_impl<Iters...>(iters...) {}
|
|
|
};
|
|
|
-}
|
|
|
|
|
|
-namespace std {
|
|
|
- template <typename... T>
|
|
|
- struct iterator_traits<::iterator::zip_iterator<T...>>
|
|
|
- : std::iterator_traits<
|
|
|
- ::iterator::facade<::iterator::zip_iterator<T...>>> {
|
|
|
- // This shouldn't need to be implemented, but for some reason my traits
|
|
|
- // are not correctly deducing here.
|
|
|
- using iterator_category =
|
|
|
- common_type_t<typename iterator_traits<T>::iterator_category...>;
|
|
|
- };
|
|
|
+ template <typename... It> zip_iterator(It...) -> zip_iterator<It...>;
|
|
|
}
|
|
|
|
|
|
+template <typename... T>
|
|
|
+struct std::iterator_traits<::iterator::zip_iterator<T...>>
|
|
|
+ : std::iterator_traits<::iterator::facade<::iterator::zip_iterator<T...>>> {
|
|
|
+ // This shouldn't need to be implemented, but for some reason my traits
|
|
|
+ // are not correctly deducing here.
|
|
|
+ using iterator_category =
|
|
|
+ common_type_t<typename iterator_traits<T>::iterator_category...>;
|
|
|
+};
|
|
|
+
|
|
|
template <typename... Is>
|
|
|
iterator::zip_iterator<Is...> make_zip_iterator(Is &&... iters) {
|
|
|
return {std::forward<Is>(iters)...};
|