VCCC  2024.05
VisualCamp Common C++ library
zip_transform_view.hpp
Go to the documentation of this file.
1 //
2 // Created by YongGyu Lee on 4/9/24.
3 //
4 
5 #ifndef VCCC_RANGES_VIEWS_ZIP_TRANSFORM_VIEW_HPP_
6 #define VCCC_RANGES_VIEWS_ZIP_TRANSFORM_VIEW_HPP_
7 
8 #include <tuple>
9 #include <type_traits>
10 #include <utility>
11 
27 #include "vccc/__ranges/range.hpp"
31 #include "vccc/__ranges/view.hpp"
42 
43 namespace vccc {
44 namespace ranges {
45 namespace detail {
46 
48 struct zip_transform_view_iterator_category {
49 #if __cplusplus < 202002L
50  using iterator_category = iterator_ignore;
51 #endif
52 };
53 
54 template<bool Const, typename Base, typename F, typename... Views>
55 struct zip_transform_view_iterator_category<Const, Base, F, type_sequence<Views...>, true> {
56  private:
57  using MF = maybe_const<Const, F>;
58  template<typename View>
59  using IC = typename cxx20_iterator_traits<iterator_t< maybe_const<Const, View> >>::iterator_category;
60 
61  template<typename BaseC>
62  using POT_derived_from = conjunction<derived_from<Views, BaseC>...>;
63 
64  public:
65  using iterator_category =
66  std::conditional_t<
67  negation<is_referencable< invoke_result_t<MF&, range_reference_t<maybe_const<Const, Views>>...> >>::value, input_iterator_tag,
68  std::conditional_t<
70  std::conditional_t<
72  std::conditional_t<
75  >>>>;
76 };
77 
78 } // namespace detail
79 
82 
83 template<typename F, typename... Views>
84 class zip_transform_view : public view_interface<zip_transform_view<Views...>> {
85  public:
86  static_assert(move_constructible<F>::value, "Constraints not satisfied");
87  static_assert(conjunction<input_range<Views>...>::value, "Constraints not satisfied");
88  static_assert(conjunction<view<Views>...>::value, "Constraints not satisfied");
89  static_assert(sizeof...(Views) > 0, "Constraints not satisfied");
90  static_assert(std::is_object<F>::value, "Constraints not satisfied");
91  static_assert(regular_invocable<F&, range_reference_t<Views>...>::value, "Constraints not satisfied");
92  static_assert(is_referencable<invoke_result_t<F&, range_reference_t<Views>...>>::value, "Constraints not satisfied");
93 
94  using tuple_index_sequence = std::index_sequence_for<Views...>;
95 
96  template<bool Const> class sentinel;
97  template<bool Const> class iterator;
98 
99  private:
100  using InnerView = zip_view<Views...>;
101  template<bool Const> using ziperator = iterator_t<maybe_const<Const, InnerView>>;
102  template<bool Const> using zentinel = sentinel_t<maybe_const<Const, InnerView>>;
103 
104 
105  public:
106  template<bool Const>
107  class iterator
108  : public detail::zip_transform_view_iterator_category<
109  Const,
110  InnerView,
111  F,
112  type_sequence<Views...>>
113  {
115  using Base = maybe_const<Const, InnerView>;
116 
117  friend class iterator<false>;
118  friend class sentinel<true>;
119  friend class sentinel<false>;
120  friend class zip_transform_view;
121 
122  struct deref_fn {
123  private:
124  struct impl {
125  template<typename Tuple, std::size_t... I>
126  decltype(auto) operator()(const F& f, const Tuple& t, std::index_sequence<I...>)
127  noexcept(noexcept(vccc::invoke(f, std::get<I>(t)...)))
128  {
129  return vccc::invoke(f, std::get<I>(t)...);
130  }
131  };
132 
133  public:
134  template<typename Tuple>
135  decltype(auto) operator()(const F& f, const Tuple& t)
136  noexcept(noexcept(vccc::invoke(impl{}, f, t, tuple_index_sequence{})))
137  {
138  return impl{}(f, t, tuple_index_sequence{});
139  }
140 
141  };
142 
143  public:
144 
145  using iterator_concept = typename ziperator<Const>::iterator_concept;
146  using value_type = std::conditional_t<Const,
150 
151 #if __cplusplus < 202002L
152  using pointer = void;
153  using reference = invoke_result_t<deref_fn, const F&, decltype(*std::declval<ziperator<Const>&>())>;
154 #endif
155 
156  iterator() = default;
157 
158  template<bool AntiConst, std::enable_if_t<conjunction<
159  bool_constant<((Const != AntiConst) && Const)>,
160  convertible_to<ziperator<false>, ziperator<Const>>
161  >::value, int> = 0>
163  : parent_(std::move(i.parent_)), inner_(std::move(i.inner_)) {}
164 
165  constexpr decltype(auto) operator*() const
166  noexcept(noexcept(vccc::invoke(deref_fn{}, *parent_->fun_, *inner_)))
167  {
168  return deref_fn{}(*parent_->fun_, *inner_);
169  }
170 
172  constexpr decltype(auto) operator[](difference_type n) const {
173  return vccc::apply(
174  [&](const auto&... iters) -> decltype(auto) {
175  return vccc::invoke(*parent_->fun_, iters[iter_difference_t<remove_cvref_t<decltype(iters)>>(n)]...);
176  }
177  );
178  }
179 
180  constexpr iterator& operator++() {
181  ++inner_;
182  return *this;
183  }
184 
186  constexpr void operator++(int) {
187  ++*this;
188  }
189 
191  constexpr iterator operator++(int) {
192  auto tmp = *this;
193  ++*this;
194  return tmp;
195  }
196 
198  constexpr iterator& operator--() {
199  --inner_;
200  return *this;
201  }
202 
204  constexpr iterator operator--(int) {
205  auto tmp = *this;
206  --*this;
207  return tmp;
208  }
209 
212  inner_ += n;
213  return *this;
214  }
215 
218  inner_ -= n;
219  return *this;
220  }
221 
222  template<typename Z = ziperator<Const>, std::enable_if_t<equality_comparable<Z>::value, int> = 0>
223  friend constexpr bool operator==(const iterator& x, const iterator& y) {
224  return x.inner_ == y.inner_;
225  }
226 
227  template<typename Z = ziperator<Const>, std::enable_if_t<equality_comparable<Z>::value, int> = 0>
228  friend constexpr bool operator!=(const iterator& x, const iterator& y) {
229  return !(x.inner_ == y.inner_);
230  }
231 
232  template<typename Z = ziperator<Const>, std::enable_if_t<conjunction<
233  random_access_range<Z>,
234  unstable_three_way_comparable<Z>
235  >::value, int> = 0>
236  friend constexpr bool operator<(const iterator& x, const iterator& y) {
237  return x.inner_ < y.inner_;
238  }
239 
240  template<typename Z = ziperator<Const>, std::enable_if_t<conjunction<
241  random_access_range<Z>,
242  unstable_three_way_comparable<Z>
243  >::value, int> = 0>
244  friend constexpr bool operator<=(const iterator& x, const iterator& y) {
245  using namespace vccc::rel_ops;
246  return x <= y;
247  }
248 
249  template<typename Z = ziperator<Const>, std::enable_if_t<conjunction<
250  random_access_range<Z>,
251  unstable_three_way_comparable<Z>
252  >::value, int> = 0>
253  friend constexpr bool operator>(const iterator& x, const iterator& y) {
254  using namespace vccc::rel_ops;
255  return x > y;
256  }
257 
258  template<typename Z = ziperator<Const>, std::enable_if_t<conjunction<
259  random_access_range<Z>,
260  unstable_three_way_comparable<Z>
261  >::value, int> = 0>
262  friend constexpr bool operator>=(const iterator& x, const iterator& y) {
263  using namespace vccc::rel_ops;
264  return x >= y;
265  }
266 
268  friend constexpr iterator operator+(const iterator& i, difference_type n) {
269  return iterator(*i.parent_, i.inner_ + n);
270  }
271 
273  friend constexpr iterator operator+(difference_type n, const iterator& i) {
274  return iterator(*i.parent_, i.inner_ + n);
275  }
276 
278  friend constexpr iterator operator-(const iterator& i, difference_type n) {
279  return iterator(*i.parent_, i.inner_ - n);
280  }
281 
282  template<typename Z = ziperator<Const>, std::enable_if_t<sized_sentinel_for<Z, Z>::value, int> = 0>
283  friend constexpr difference_type operator-(const iterator& i, const iterator& j) {
284  return i.inner_ - j.inner_;
285  }
286 
287  private:
288  VCCC_CONSTEXPR_AFTER_CXX17 iterator(Parent& parent, ziperator<Const> inner)
289  : parent_(std::addressof(parent)), inner_(std::move(inner)) {}
290 
291  Parent* parent_{};
292  ziperator<Const> inner_{};
293  };
294 
295  template<bool Const>
296  class sentinel {
297  friend class sentinel<false>;
298  friend class zip_transform_view;
299 
300  public:
301  sentinel() = default;
302 
303  template<bool AntiConst, std::enable_if_t<conjunction<
304  bool_constant<((Const != AntiConst) && Const)>,
305  convertible_to<zentinel<false>, zentinel<Const>>
306  >::value, int> = 0>
308  : inner_(std::move(i.inner_)) {}
309 
310  template<bool OtherConst, std::enable_if_t<sentinel_for<zentinel<Const>, ziperator<OtherConst>>::value, int> = 0>
311  friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y) {
312  return y.equal_to(x);
313  }
314 
315  template<bool OtherConst, std::enable_if_t<sentinel_for<zentinel<Const>, ziperator<OtherConst>>::value, int> = 0>
316  friend constexpr bool operator==(const sentinel& y, const iterator<OtherConst>& x) {
317  return x == y;
318  }
319 
320  template<bool OtherConst, std::enable_if_t<sentinel_for<zentinel<Const>, ziperator<OtherConst>>::value, int> = 0>
321  friend constexpr bool operator!=(const iterator<OtherConst>& x, const sentinel& y) {
322  return !(x == y);
323  }
324 
325  template<bool OtherConst, std::enable_if_t<sentinel_for<zentinel<Const>, ziperator<OtherConst>>::value, int> = 0>
326  friend constexpr bool operator!=(const sentinel& y, const iterator<OtherConst>& x) {
327  return !(x == y);
328  }
329 
330  template<bool OtherConst, std::enable_if_t<sized_sentinel_for<zentinel<Const>, ziperator<OtherConst>>::value, int> = 0>
333  return x.inner_ - y.inner_;
334  }
335 
336  template<bool OtherConst, std::enable_if_t<sized_sentinel_for<zentinel<Const>, ziperator<OtherConst>>::value, int> = 0>
339  return y.inner_ - x.inner_;
340  }
341 
342  private:
343  constexpr explicit sentinel(zentinel<Const> inner)
344  : inner_(std::move(inner)) {}
345 
346  template<bool OtherConst>
347  constexpr bool equal_to(const iterator<OtherConst>& x) const {
348  return x.inner_ == inner_;
349  }
350 
351  zentinel<Const> inner_{};
352  };
353 
354  zip_transform_view() = default;
355 
356  constexpr zip_transform_view(F fun, Views... views)
357  : fun_(std::move(fun)), zip_(std::move(views)...) {}
358 
359  constexpr iterator<false> begin() {
360  return iterator<false>(*this, zip_.begin());
361  }
362 
363  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
364  range<const zip_view<Views...>>
365  >::value, int> = 0>
366  constexpr iterator<true> begin() const {
367  return iterator<true>(*this, zip_.begin());
368  }
369 
370  constexpr auto end() {
371  return end_impl<false>(*this, common_range<InnerView>{});
372  }
373 
374  constexpr auto end() const {
375  return end_impl<true>(*this, common_range<const InnerView>{});
376  }
377 
378  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
379  sized_range<InnerView>
380  >::value, int> = 0>
381  constexpr auto size() {
382  return zip_.size();
383  }
384 
385  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
386  sized_range<const InnerView>
387  >::value, int> = 0>
388  constexpr auto size() const {
389  return zip_.size();
390  }
391 
392  private:
393  template<bool Const, typename Self>
394  static constexpr iterator<Const> end_impl(Self&& self, std::true_type /* common_range */) {
395  return iterator<Const>(self, self.zip_.end());
396  }
397 
398  template<bool Const, typename Self>
399  static constexpr sentinel<Const> end_impl(Self&& self, std::false_type /* common_range */) {
400  return sentinel<Const>(self.zip_.end());
401  }
402 
403  movable_box<F> fun_{};
404  InnerView zip_{};
405 };
406 
407 #if __cplusplus >= 201703L
408 
409 template<typename F, typename... Rs>
411 
412 #endif
413 
415 
416 } // namespace ranges
417 } // namespace vccc
418 
419 #endif // VCCC_RANGES_VIEWS_ZIP_TRANSFORM_VIEW_HPP_
helper class template for defining a view, using the curiously recurring template pattern
Definition: view_interface.hpp:78
Definition: zip_transform_view.hpp:113
constexpr iterator & operator--()
Definition: zip_transform_view.hpp:198
constexpr friend iterator operator+(const iterator &i, difference_type n)
Definition: zip_transform_view.hpp:268
constexpr iterator(iterator<!Const > i)
Definition: zip_transform_view.hpp:162
constexpr friend iterator operator-(const iterator &i, difference_type n)
Definition: zip_transform_view.hpp:278
void pointer
Definition: zip_transform_view.hpp:152
typename ziperator< Const >::iterator_concept iterator_concept
Definition: zip_transform_view.hpp:145
constexpr void operator++(int)
Definition: zip_transform_view.hpp:186
std::conditional_t< Const, remove_cvref_t< invoke_result_t< const F &, range_reference_t< const Views >... > >, remove_cvref_t< invoke_result_t< F &, range_reference_t< Views >... > >> value_type
Definition: zip_transform_view.hpp:148
invoke_result_t< deref_fn, const F &, decltype(*std::declval< ziperator< Const > & >())> reference
Definition: zip_transform_view.hpp:153
constexpr friend bool operator<(const iterator &x, const iterator &y)
Definition: zip_transform_view.hpp:236
constexpr friend bool operator==(const iterator &x, const iterator &y)
Definition: zip_transform_view.hpp:223
friend class zip_transform_view
Definition: zip_transform_view.hpp:120
constexpr friend bool operator!=(const iterator &x, const iterator &y)
Definition: zip_transform_view.hpp:228
constexpr iterator & operator-=(difference_type n)
Definition: zip_transform_view.hpp:217
constexpr iterator & operator+=(difference_type n)
Definition: zip_transform_view.hpp:211
constexpr iterator operator--(int)
Definition: zip_transform_view.hpp:204
constexpr friend bool operator>(const iterator &x, const iterator &y)
Definition: zip_transform_view.hpp:253
constexpr friend bool operator<=(const iterator &x, const iterator &y)
Definition: zip_transform_view.hpp:244
constexpr friend iterator operator+(difference_type n, const iterator &i)
Definition: zip_transform_view.hpp:273
constexpr iterator operator++(int)
Definition: zip_transform_view.hpp:191
constexpr friend bool operator>=(const iterator &x, const iterator &y)
Definition: zip_transform_view.hpp:262
constexpr friend difference_type operator-(const iterator &i, const iterator &j)
Definition: zip_transform_view.hpp:283
constexpr iterator & operator++()
Definition: zip_transform_view.hpp:180
range_difference_t< Base > difference_type
Definition: zip_transform_view.hpp:149
friend class iterator< false >
Definition: zip_transform_view.hpp:117
Definition: zip_transform_view.hpp:296
constexpr friend bool operator==(const sentinel &y, const iterator< OtherConst > &x)
Definition: zip_transform_view.hpp:316
constexpr sentinel(sentinel< AntiConst > i)
Definition: zip_transform_view.hpp:307
constexpr friend bool operator!=(const sentinel &y, const iterator< OtherConst > &x)
Definition: zip_transform_view.hpp:326
constexpr friend bool operator==(const iterator< OtherConst > &x, const sentinel &y)
Definition: zip_transform_view.hpp:311
constexpr friend bool operator!=(const iterator< OtherConst > &x, const sentinel &y)
Definition: zip_transform_view.hpp:321
constexpr friend range_difference_t< maybe_const< OtherConst, InnerView > > operator-(const iterator< OtherConst > &x, const sentinel &y)
Definition: zip_transform_view.hpp:332
constexpr friend range_difference_t< maybe_const< OtherConst, InnerView > > operator-(const sentinel &y, const iterator< OtherConst > &x)
Definition: zip_transform_view.hpp:338
Definition: zip_transform_view.hpp:84
constexpr auto size() const
Definition: zip_transform_view.hpp:388
constexpr auto size()
Definition: zip_transform_view.hpp:381
constexpr auto end()
Definition: zip_transform_view.hpp:370
constexpr auto end() const
Definition: zip_transform_view.hpp:374
constexpr iterator< true > begin() const
Definition: zip_transform_view.hpp:366
constexpr iterator< false > begin()
Definition: zip_transform_view.hpp:359
std::index_sequence_for< Views... > tuple_index_sequence
Definition: zip_transform_view.hpp:94
constexpr zip_transform_view(F fun, Views... views)
Definition: zip_transform_view.hpp:356
#define VCCC_CONSTEXPR_AFTER_CXX17
Definition: constexpr.hpp:20
constexpr invoke_result_t< F, Args... > invoke(F &&f, Args &&... args) noexcept(is_nothrow_invocable< F, Args... >::value)
Definition: invoke.hpp:38
std::forward_iterator_tag forward_iterator_tag
Definition: iterator_tag.hpp:17
std::random_access_iterator_tag random_access_iterator_tag
Definition: iterator_tag.hpp:19
typename iter_difference< T >::type iter_difference_t
Computes the difference type of T
Definition: iter_difference_t.hpp:49
std::input_iterator_tag input_iterator_tag
Definition: iterator_tag.hpp:15
std::bidirectional_iterator_tag bidirectional_iterator_tag
Definition: iterator_tag.hpp:18
std::enable_if_t< std::is_object< T >::value, T * > addressof(T &t) noexcept
Definition: addressof.hpp:33
constexpr auto get(const subrange< I, S, K > &r)
Definition: subrange.hpp:371
typename sentinel< R >::type sentinel_t
Definition: sentinel_t.hpp:29
typename ranges::iterator< T >::type iterator_t
Definition: iterator_t.hpp:32
typename range_difference< R >::type range_difference_t
Used to obtain the difference type of the iterator type of range type R.
Definition: range_difference_t.hpp:41
typename range_reference< R >::type range_reference_t
Used to obtain the reference type of the iterator type of range type R.
Definition: range_reference_t.hpp:42
constexpr decltype(auto) apply(F &&f, Tuple &&t)
calls a function with the elements of tuple of arguments
Definition: apply.hpp:89
std::integral_constant< bool, v > bool_constant
Definition: bool_constant.hpp:19
typename remove_cvref< T >::type remove_cvref_t
Definition: remove_cvref.hpp:24
typename invoke_result< F, Args... >::type invoke_result_t
Definition: is_invocable.hpp:66
std::conditional_t< Const, const V, V > maybe_const
Definition: maybe_const.hpp:16
Definition: matrix.hpp:495
Definition: cxx20_rel_ops.hpp:17
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35
Definition: conjunction.hpp:22
Models std::convertible_to
Definition: convertible_to.hpp:38
Definition: is_referenceable.hpp:18
Definition: common_range.hpp:41
Definition: equal_to.hpp:20
specifies a range whose iterator type satisfies input_iterator
Definition: input_range.hpp:46
specifies that a range is a view, that is, it has constant time copy/move/assignment
Definition: view.hpp:31
specifies that a callable type can be invoked with a given set of argument types
Definition: invocable.hpp:64