VCCC  2024.05
VisualCamp Common C++ library
transform_view.hpp
Go to the documentation of this file.
1 //
2 // Created by yonggyulee on 1/11/24.
3 //
4 
5 #ifndef VCCC_RANGES_VIEWS_TRANSFORM_VIEW_HPP
6 #define VCCC_RANGES_VIEWS_TRANSFORM_VIEW_HPP
7 
8 #include <memory>
9 #include <type_traits>
10 #include <utility>
11 
20 #include "vccc/__ranges/begin.hpp"
27 #include "vccc/__ranges/range.hpp"
31 #include "vccc/__ranges/view.hpp"
40 
41 namespace vccc {
42 namespace ranges {
43 namespace detail {
44 
45 template<typename C>
46 struct transform_view_iterator_category_2 {
47  using type = C;
48 };
49 template<>
50 struct transform_view_iterator_category_2<contiguous_iterator_tag> {
51  using type = random_access_iterator_tag;
52 };
53 
54 }
55 
58 
59 template<typename V, typename F>
60 class transform_view : public view_interface<transform_view<V, F>> {
61  public:
62  static_assert(input_range<V>::value, "Constraints not satisfied");
63  static_assert(copy_constructible<F>::value, "Constraints not satisfied");
64  static_assert(view<V>::value, "Constraints not satisfied");
65  static_assert(std::is_object<F>::value, "Constraints not satisfied");
66  static_assert(regular_invocable<F&, range_reference_t<V>>::value, "Constraints not satisfied");
67 
68  private:
69 
71  struct transform_view_iterator_category {
72 #if __cplusplus < 202002L
73  using iterator_category = iterator_ignore;
74 #endif
75  };
76  template<typename Base>
77  struct transform_view_iterator_category<Base, true> {
78  using iterator_category =
79  std::conditional_t<
80  std::is_reference<invoke_result_t<F&, range_reference_t<Base>>>::value,
81  detail::transform_view_iterator_category_2<typename cxx20_iterator_traits<iterator_t<Base>>::iterator_category>,
83  >;
84  };
85 
86  public:
87  template<bool Const> class iterator;
88  template<bool Const> friend class iterator;
89 
90  template<bool Const> class sentinel;
91 
92  template<bool Const>
93  class iterator : public transform_view_iterator_category<std::conditional_t<Const, const V, V>> {
94  using Parent = std::conditional_t<Const, const transform_view, transform_view>;
95  using Base = maybe_const<Const, V>;
96 
97  template<bool B> friend class sentinel;
98  friend class transform_view;
99  public:
101  std::conditional_t<
103  std::conditional_t<
105  std::conditional_t<
108  >>>;
111 #if __cplusplus < 202002L
112  using pointer = void;
113  using reference = invoke_result_t<decltype(std::declval<F&>()), decltype(*std::declval<iterator_t<Base>&>())>;
114 #endif
115 
116  iterator() = default;
117 
118  constexpr iterator(Parent& parent, iterator_t<Base> current)
119  : current_(std::move(current)), parent_(vccc::addressof(parent)) {}
120 
121  template<bool AntiConst, std::enable_if_t<conjunction<
122  bool_constant<((Const != AntiConst) && Const)>,
124  >::value, int> = 0>
126  : current_(std::move(i.current_)), parent_(i.praent_) {}
127 
128  constexpr const iterator_t<Base>& base() const & noexcept { return current_; }
129  constexpr iterator_t<Base> base() && { return std::move(current_); }
130 
131  constexpr decltype(auto) operator*() const {
132  return vccc::invoke(*parent_->func_, *current_);
133  }
134 
136  constexpr decltype(auto) operator[](difference_type n) const {
137  return vccc::invoke(*parent_->func_, current_[n]);
138  }
139 
140  constexpr iterator& operator++() {
141  ++current_;
142  return *this;
143  }
144 
146  constexpr void operator++(int) {
147  ++current_;
148  }
149 
151  constexpr iterator operator++(int) {
152  auto tmp = *this;
153  ++*this;
154  return tmp;
155  }
156 
158  constexpr iterator& operator--() {
159  --current_;
160  return *this;
161  }
162 
164  constexpr iterator operator--(int) {
165  auto tmp = *this;
166  --*this;
167  return tmp;
168  }
169 
172  current_ += n;
173  return *this;
174  }
175 
178  current_ -= n;
179  return *this;
180  }
181 
182  template<typename B = Base, std::enable_if_t<equality_comparable<iterator_t<B>>::value, int> = 0>
183  friend constexpr bool operator==(const iterator& x, const iterator& y) {
184  return x.current_ == y.current_;
185  }
186 
187  template<typename B = Base, std::enable_if_t<equality_comparable<iterator_t<B>>::value, int> = 0>
188  friend constexpr bool operator!=(const iterator& x, const iterator& y) {
189  return !(x == y);
190  }
191 
193  friend constexpr bool operator<(const iterator& x, const iterator& y) {
194  return x.current_ < y.current_;
195  }
196 
198  friend constexpr bool operator>(const iterator& x, const iterator& y) {
199  return y < x;
200  }
201 
203  friend constexpr bool operator<=(const iterator& x, const iterator& y) {
204  return !(y < x);
205  }
206 
208  friend constexpr bool operator>=(const iterator& x, const iterator& y) {
209  return !(x < y);
210  }
211 
213  friend constexpr iterator operator+(iterator i, difference_type n) {
214  return iterator{*i.parent_, i.current_ + n};
215  }
216 
218  friend constexpr iterator operator+(difference_type n, iterator i) {
219  return iterator{*i.parent_, i.current_ + n};
220  }
221 
223  friend constexpr iterator operator-(iterator i, difference_type n) {
224  return iterator{*i.parent_, i.current_ - n};
225  }
226 
227  template<typename B = Base, std::enable_if_t<sized_sentinel_for<iterator_t<B>, iterator_t<B>>::value, int> = 0>
228  friend constexpr difference_type operator-(const iterator& x, const iterator& y) {
229  return x.current_ - y.current_;
230  }
231 
232  friend constexpr decltype(auto) iter_move(const iterator& i)
233  noexcept(noexcept(vccc::invoke(std::declval<const F&>(), *i.current_)))
234  {
235  return iter_move_ref(*i);
236  }
237 
238  private:
240  static constexpr decltype(auto) iter_move_ref(T&& ref) {
241  return std::forward<T>(ref);
242  }
243  template<typename T>
244  static constexpr decltype(auto) iter_move_ref(T& ref) {
245  return std::move(ref);
246  }
247 
248  iterator_t<Base> current_;
249  Parent* parent_ = nullptr;
250  };
251 
252  template<bool Const>
253  class sentinel {
254  using Parent = std::conditional_t<Const, const transform_view, transform_view>;
255  using Base = maybe_const<Const, V>;
256 
257  public:
258  sentinel() = default;
259 
260  constexpr explicit sentinel(sentinel_t<Base> end)
261  : end_(std::move(end)) {}
262 
263  template<bool AntiConst, std::enable_if_t<conjunction<
264  bool_constant<((Const != AntiConst) && Const)>,
266  >::value, int> = 0>
268  : end_(std::move(i.end_)) {}
269 
270  constexpr sentinel_t<Base> base() const {
271  return end_;
272  }
273 
274  friend constexpr bool operator==(const transform_view::iterator<Const>& x, const sentinel& y) {
275  using namespace vccc::rel_ops;
276  return x.current_ == y.end_;
277  }
278 
279  friend constexpr bool operator==(const sentinel& y, const transform_view::iterator<Const>& x) {
280  return x == y;
281  }
282 
283  friend constexpr bool operator!=(const transform_view::iterator<Const>& x, const sentinel& y) {
284  return !(x == y);
285  }
286 
287  friend constexpr bool operator!=(const sentinel& y, const transform_view::iterator<Const>& x) {
288  return !(x == y);
289  }
290 
291  template<typename B = Base, std::enable_if_t<sized_sentinel_for<sentinel_t<B>, iterator_t<B>>::value, int> = 0>
292  friend constexpr range_difference_t<B>
293  operator-(const iterator<Const>& x, const sentinel& y) {
294  return x.current_ - y.end_;
295  }
296 
297  template<typename B = Base, std::enable_if_t<sized_sentinel_for<sentinel_t<B>, iterator_t<B>>::value, int> = 0>
298  friend constexpr range_difference_t<B>
299  operator-(const sentinel& y, const iterator<Const>& x) {
300  return y.end_ - x.current_;
301  }
302 
303  private:
304  sentinel_t<Base> end_;
305  };
306 
307  transform_view() = default;
308 
309  constexpr explicit transform_view(V base, F func) : base_(std::move(base)), func_(func) {}
310 
312  constexpr V base() const& {
313  return base_;
314  }
315 
316  constexpr V base() && {
317  return std::move(base_);
318  }
319 
320  constexpr iterator<false> begin() {
321  return iterator<false>{*this, ranges::begin(base_)};
322  }
323 
324  template<typename V2 = const V, typename F2 = const F, std::enable_if_t<conjunction<
325  range<V2>,
327  >::value, int> = 0>
328  constexpr iterator<true> begin() const {
329  return iterator<true>{*this, ranges::begin(base_)};
330  }
331 
333  constexpr sentinel<false> end() {
334  return sentinel<false>{ranges::end(base_)};
335  }
336 
338  constexpr iterator<false> end() {
339  return iterator<false>{*this, ranges::end(base_)};
340  }
341 
342  template<typename V2 = const V, typename F2 = const F, std::enable_if_t<conjunction<
343  range<V2>,
346  >::value, int> = 0>
347  constexpr sentinel<true> end() const {
348  return sentinel<true>{ranges::end(base_)};
349  }
350 
351  template<typename V2 = const V, typename F2 = const F, std::enable_if_t<conjunction<
354  >::value, int> = 0>
355  constexpr iterator<true> end() const {
356  return iterator<true>{*this, ranges::end(base_)};
357  }
358 
360  constexpr auto size() {
361  return ranges::size(base_);
362  }
363 
365  constexpr auto size() const {
366  return ranges::size(base_);
367  }
368 
369  private:
370  V base_;
371  movable_box<F> func_;
372 };
373 
374 template<typename R, typename F, std::enable_if_t<conjunction<
375  input_range<views::all_t<R>>,
377  std::is_object<F>,
379 >::value, int> = 0>
380 constexpr transform_view<views::all_t<R>, F>
381 make_transform_view(R&& r, F f) {
382  return transform_view<views::all_t<R>, F>(std::forward<R>(r), std::move(f));
383 }
384 
385 #if __cplusplus >= 201703L
386 
387 template<typename R, typename F>
388 transform_view(R&&, F) -> transform_view<views::all_t<R>, F>;
389 
390 #endif
391 
393 
394 } // namespace ranges
395 } // namespace vccc
396 
397 #endif // VCCC_RANGES_VIEWS_TRANSFORM_VIEW_HPP
Definition: transform_view.hpp:93
constexpr iterator & operator--()
Definition: transform_view.hpp:158
constexpr friend iterator operator-(iterator i, difference_type n)
Definition: transform_view.hpp:223
void pointer
Definition: transform_view.hpp:112
constexpr friend iterator operator+(difference_type n, iterator i)
Definition: transform_view.hpp:218
constexpr friend difference_type operator-(const iterator &x, const iterator &y)
Definition: transform_view.hpp:228
constexpr void operator++(int)
Definition: transform_view.hpp:146
constexpr iterator(iterator< AntiConst > i)
Definition: transform_view.hpp:125
constexpr friend bool operator<(const iterator &x, const iterator &y)
Definition: transform_view.hpp:193
constexpr friend bool operator==(const iterator &x, const iterator &y)
Definition: transform_view.hpp:183
constexpr friend iterator operator+(iterator i, difference_type n)
Definition: transform_view.hpp:213
constexpr friend bool operator!=(const iterator &x, const iterator &y)
Definition: transform_view.hpp:188
constexpr iterator & operator-=(difference_type n)
Definition: transform_view.hpp:177
constexpr iterator(Parent &parent, iterator_t< Base > current)
Definition: transform_view.hpp:118
constexpr iterator & operator+=(difference_type n)
Definition: transform_view.hpp:171
constexpr iterator operator--(int)
Definition: transform_view.hpp:164
constexpr friend bool operator>(const iterator &x, const iterator &y)
Definition: transform_view.hpp:198
constexpr iterator_t< Base > base() &&
Definition: transform_view.hpp:129
constexpr friend bool operator<=(const iterator &x, const iterator &y)
Definition: transform_view.hpp:203
remove_cvref_t< invoke_result_t< F &, range_reference_t< Base > >> value_type
Definition: transform_view.hpp:109
std::conditional_t< random_access_range< Base >::value, random_access_iterator_tag, std::conditional_t< bidirectional_range< Base >::value, bidirectional_iterator_tag, std::conditional_t< forward_range< Base >::value, forward_iterator_tag, input_iterator_tag > >> iterator_concept
Definition: transform_view.hpp:108
constexpr iterator operator++(int)
Definition: transform_view.hpp:151
invoke_result_t< decltype(std::declval< F & >()), decltype(*std::declval< iterator_t< Base > & >())> reference
Definition: transform_view.hpp:113
constexpr friend bool operator>=(const iterator &x, const iterator &y)
Definition: transform_view.hpp:208
constexpr decltype(auto) friend iter_move(const iterator &i) noexcept(noexcept(vccc::invoke(std::declval< const F & >(), *i.current_)))
Definition: transform_view.hpp:232
constexpr iterator & operator++()
Definition: transform_view.hpp:140
constexpr const iterator_t< Base > & base() const &noexcept
Definition: transform_view.hpp:128
range_difference_t< Base > difference_type
Definition: transform_view.hpp:110
Definition: transform_view.hpp:253
constexpr sentinel_t< Base > base() const
Definition: transform_view.hpp:270
constexpr sentinel(sentinel< AntiConst > i)
Definition: transform_view.hpp:267
constexpr friend bool operator==(const sentinel &y, const transform_view::iterator< Const > &x)
Definition: transform_view.hpp:279
constexpr friend bool operator==(const transform_view::iterator< Const > &x, const sentinel &y)
Definition: transform_view.hpp:274
constexpr friend range_difference_t< B > operator-(const sentinel &y, const iterator< Const > &x)
Definition: transform_view.hpp:299
constexpr friend range_difference_t< B > operator-(const iterator< Const > &x, const sentinel &y)
Definition: transform_view.hpp:293
constexpr friend bool operator!=(const sentinel &y, const transform_view::iterator< Const > &x)
Definition: transform_view.hpp:287
constexpr sentinel(sentinel_t< Base > end)
Definition: transform_view.hpp:260
constexpr friend bool operator!=(const transform_view::iterator< Const > &x, const sentinel &y)
Definition: transform_view.hpp:283
Definition: transform_view.hpp:60
constexpr V base() const &
Definition: transform_view.hpp:312
constexpr transform_view(V base, F func)
Definition: transform_view.hpp:309
constexpr auto size() const
Definition: transform_view.hpp:365
constexpr auto size()
Definition: transform_view.hpp:360
constexpr sentinel< false > end()
Definition: transform_view.hpp:333
constexpr sentinel< true > end() const
Definition: transform_view.hpp:347
constexpr iterator< true > begin() const
Definition: transform_view.hpp:328
constexpr V base() &&
Definition: transform_view.hpp:316
constexpr iterator< false > end()
Definition: transform_view.hpp:338
constexpr iterator< false > begin()
Definition: transform_view.hpp:320
constexpr iterator< true > end() const
Definition: transform_view.hpp:355
helper class template for defining a view, using the curiously recurring template pattern
Definition: view_interface.hpp:78
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
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
typename sentinel< R >::type sentinel_t
Definition: sentinel_t.hpp:29
typename ranges::iterator< T >::type iterator_t
Definition: iterator_t.hpp:32
constexpr VCCC_INLINE_OR_STATIC detail::begin_niebloid begin
returns an iterator to the beginning of a range
Definition: begin.hpp:116
constexpr VCCC_INLINE_OR_STATIC detail::size_niebloid size
returns the size of a container or array
Definition: size.hpp:145
constexpr VCCC_INLINE_OR_STATIC detail::end_niebloid end
returns a sentinel indicating the end of a range
Definition: end.hpp:120
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 transform_view< views::all_t< R >, F > make_transform_view(R &&r, F f)
Definition: transform_view.hpp:381
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
specifies that an object of a type can be copy constructed and move constructed
Definition: copy_constructible.hpp:55
Definition: iterator_tag.hpp:28
Definition: negation.hpp:23
specifies a range whose iterator type satisfies bidirectional_iterator
Definition: bidirectional_range.hpp:49
Definition: common_range.hpp:41
specifies a range whose iterator type satisfies forward_iterator
Definition: forward_range.hpp:47
specifies a range whose iterator type satisfies input_iterator
Definition: input_range.hpp:46
specifies a range whose iterator type satisfies random_access_iterator
Definition: random_access_range.hpp:48
specifies that a type is a range, that is, it provides a begin iterator and an end sentinel
Definition: range.hpp:53
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