VCCC  2024.05
VisualCamp Common C++ library
to.hpp
Go to the documentation of this file.
1 //
2 // Created by yonggyulee on 2024/01/06.
3 //
4 
5 #ifndef VCCC_RANGES_TO_HPP_
6 #define VCCC_RANGES_TO_HPP_
7 
8 #include <iterator>
9 #include <tuple>
10 #include <type_traits>
11 #include <utility>
12 
22 #include "vccc/__ranges/begin.hpp"
23 #include "vccc/__ranges/end.hpp"
32 #include "vccc/__ranges/size.hpp"
34 #include "vccc/__ranges/view.hpp"
48 
49 
50 namespace vccc {
51 namespace ranges {
52 namespace detail {
53 template<typename T, typename N, typename = void>
54 struct has_mf_reserve : std::false_type {};
55 template<typename T, typename N>
56 struct has_mf_reserve<T, N, void_t<decltype( std::declval<T&>().reserve(std::declval<N>()) )>> : std::true_type {};
57 
58 template<typename T, typename N, typename = void>
59 struct has_mf_capacity : std::false_type {};
60 template<typename T, typename N>
61 struct has_mf_capacity<T, N, void_t<decltype( std::declval<T&>().capacity() )>>
62  : same_as<decltype(std::declval<T&>().capacity()), N> {};
63 
64 template<typename T, typename N, typename = void>
65 struct has_mf_max_size : std::false_type {};
66 template<typename T, typename N>
67 struct has_mf_max_size<T, N, void_t<decltype( std::declval<T&>().max_size() )>>
68  : same_as<decltype(std::declval<T&>().max_size()), N> {};
69 
71 struct reservable_container
72  : conjunction<
73  has_mf_reserve<Container, range_size_t<Container>>,
74  has_mf_reserve<Container, range_size_t<Container>>,
75  has_mf_reserve<Container, range_size_t<Container>>
76  >{};
77 template<typename Container>
78 struct reservable_container<Container, false> : std::false_type {};
79 
80 template<typename C, typename R, std::enable_if_t<conjunction<sized_range<R>, reservable_container<C>>::value, int> = 0>
81 constexpr void try_reserve(C& c, R&& r) {
82  c.reserve(static_cast<range_size_t<C>>(ranges::size(r)));
83 }
84 template<typename C, typename R, std::enable_if_t<conjunction<sized_range<R>, reservable_container<C>>::value == false, int> = 0>
85 constexpr void try_reserve(C&, R&&) {}
86 
87 template<typename T, typename U, typename = void>
88 struct has_mf_push_back : std::false_type {};
89 template<typename T, typename U>
90 struct has_mf_push_back<T, U, void_t<decltype( std::declval<T&>().push_back(std::declval<U>()) )>>
91  : std::true_type {};
92 
93 template<typename T, typename = void>
94 struct has_mf_end : std::false_type {};
95 template<typename T>
96 struct has_mf_end<T, void_t<decltype( std::declval<T&>().end() )>>
97  : is_referencable<decltype( std::declval<T&>().end() )> {};
98 
100 struct has_mf_insert : std::false_type {};
101 template<typename T, typename U>
102 struct has_mf_insert<T, U, true, void_t<decltype( std::declval<T&>().insert(std::declval<T&>().end(), std::declval<U>()) )>>
103  : std::true_type {};
104 
105 template<typename Container, typename Reference, bool = conjunction<is_referencable<Container>, is_referencable<Reference>>::value>
106 struct container_insertable
107  : disjunction<
108  has_mf_push_back<Container, Reference>,
109  has_mf_insert<Container, Reference>
110  > {};
111 
113 constexpr auto container_inserter(C& c) {
114  return std::back_inserter(c);
115 }
116 
118 constexpr auto container_inserter(C& c) {
119  return std::inserter(c, c.end());
120 }
121 
123 struct container_compatible_range : convertible_to<range_reference_t<R>, T> {};
124 template<typename R, typename T>
125 struct container_compatible_range<R, T, false> : std::false_type {};
126 
127 using vccc::detail::tag_1;
128 using vccc::detail::tag_2;
129 using vccc::detail::tag_3;
130 using vccc::detail::tag_4;
131 using vccc::detail::tag_5;
132 
133 template<bool /* false */, typename C, typename R, typename... Args>
134 struct ranges_to_1_a_3_impl : std::false_type {};
135 template<typename C, typename R, typename... Args>
136 struct ranges_to_1_a_3_impl<true, C, R, Args...>
137  : conjunction<
138  derived_from<typename cxx20_iterator_traits<iterator_t<R>>::iterator_category, input_iterator_tag>,
139  constructible_from<C, iterator_t<R>, sentinel_t<R>, Args...>
140  > {};
141 
142 template<bool /* common_range = false */, typename C, typename R, typename... Args>
143 struct ranges_to_1_a_3 : std::false_type {};
144 template<typename C, typename R, typename... Args>
145 struct ranges_to_1_a_3<true, C, R, Args...>
146  : ranges_to_1_a_3_impl<
147  vccc::detail::has_typename_iterator_category< cxx20_iterator_traits<iterator_t<R>> >::value,
148  C,
149  R,
150  Args...> {};
151 
152 template<typename C, typename R, typename... Args>
153 struct ranges_to_1_a_4
154  : conjunction<
155  constructible_from<C, Args...>,
156  container_insertable<C, range_reference_t<R>>
157  > {};
158 
159 template<typename C, typename R, typename... Args>
160 struct ranges_to_1_a {
161  using tag =
162  std::conditional_t<
163  constructible_from<C, R, Args...>::value, tag_1,
164  std::conditional_t<
165  constructible_from<C, from_range_t, R, Args...>::value, tag_2,
166  std::conditional_t<
167  ranges_to_1_a_3<common_range<R>::value, C, R, Args...>::value, tag_3,
168  std::conditional_t<
169  ranges_to_1_a_4<C, R, Args...>::value, tag_4,
170  tag_else
171  >>>>;
172 };
173 
174 template<typename C, bool = has_typename_type<range_reference<C>>::value/* false */>
175 struct ranges_to_1_b {
176  using tag = tag_else;
177 };
178 template<typename C>
179 struct ranges_to_1_b<C, true> {
180  using tag = std::conditional_t<input_range<range_reference_t<C>>::value, tag_5, tag_else>;
181 };
182 
183 // std::tuple is convertible to std::pair since C++23
184 template<typename T, typename U>
185 struct tuple_convertible_to : convertible_to<T, U> {};
186 #if __cplusplus < 202302L
187 template<typename T1, typename T2, typename U1, typename U2>
188 struct tuple_convertible_to<std::tuple<T1, T2>, std::pair<U1, U2>>
189  : conjunction<convertible_to<T1, U1>, convertible_to<T2, U2>> {};
190 #endif
191 
192 template<typename C, typename R, typename... Args>
193 struct ranges_to_1
194  : std::conditional_t<
195  disjunction<
196  negation<input_range<C>>,
197  tuple_convertible_to<range_reference_t<R>, range_value_t<C>>
198  >::value,
199  ranges_to_1_a<C, R, Args...>,
200  ranges_to_1_b<C>
201  > {};
202 
203 template<typename C, typename R, typename... Args>
204 using ranges_to_1_tag = typename ranges_to_1<C, R, Args...>::tag;
205 
206 template<typename C, typename R, typename... Args>
207 constexpr C to_1(tag_1, R&& r, Args&&... args) {
208  return C(std::forward<R>(r), std::forward<Args>(args)...);
209 }
210 
211 template<typename C, typename R, typename... Args>
212 constexpr C to_1(tag_2, R&& r, Args&&... args) {
213  return C(from_range, std::forward<R>(r), std::forward<Args>(args)...);
214 }
215 
216 template<typename C, typename R, typename... Args>
217 constexpr C to_1_kv(std::false_type, R&& r, Args&&... args) {
218  return C(ranges::begin(r), ranges::end(r), std::forward<Args>(args)...);
219 }
220 
221 template<typename C, typename R, typename... Args>
222 constexpr C to_1_kv(std::true_type, R&& r, Args&&... args) {
223  return to_1_kv<C>(std::false_type{}, std::forward<R>(r) | views::transform([](auto&& tup) {
224  return range_value_t<C>(std::get<0>(std::forward<decltype(tup)>(tup)), std::get<1>(std::forward<decltype(tup)>(tup)));
225  }), std::forward<Args>(args)...);
226 }
227 
228 template<typename C, typename R, typename... Args>
229 constexpr C to_1(tag_3, R&& r, Args&&... args) {
230 #if __cplusplus < 202302L
231  return to_1_kv<C>(is_specialization<range_reference_t<R>, std::tuple>{}, std::forward<R>(r), std::forward<Args>(args)...);
232 #else
233  return C(ranges::begin(r), ranges::end(r), std::forward<Args>(args)...);
234 #endif
235 }
236 
237 template<typename C, typename R, typename... Args>
238 constexpr C to_1(tag_4, R&& r, Args&&... args) {
239  C c(std::forward<Args>(args)...);
240  detail::try_reserve(c, std::forward<R>(r));
241  ranges::copy(std::forward<R>(r), detail::container_inserter<range_reference_t<R>>(c));
242  return c;
243 }
244 
245 template<typename C, typename R, typename... Args>
246 constexpr C to_1(tag_5, R&& r, Args&&... args);
247 
248 
249 // ranges::to< template<typename...> >
250 
251 template<typename R>
252 struct ranges_to_input_iterator {
253  using iterator_category = input_iterator_tag;
254  using value_type = range_value_t<R>;
255  using difference_type = std::ptrdiff_t;
256  using pointer = std::add_pointer_t<range_reference_t<R>>;
257  using reference = range_reference_t<R>;
258 
259  reference operator*() const;
260  pointer operator->() const;
261  ranges_to_input_iterator& operator++();
262  ranges_to_input_iterator operator++(int);
263  bool operator==(const ranges_to_input_iterator&) const;
264 };
265 
266 
267 // template<typename R, bool = is_key_value_range<R>::value /* false */>
268 // struct range_to_alloc {};
269 // template<typename R>
270 // struct range_to_alloc<R, true> {
271 // using type = std::pair<std::add_const_t<typename range_value_t<R>::first_type>,
272 // typename range_value_t<R>::second_type>;
273 // };
274 // template<typename R>
275 // using range_to_alloc_t = typename range_to_alloc<R>::type;
276 
277 
278 
279 // #if __cplusplus >= 201703L
280 // template<template<typename...> class C, typename R, typename... Args>
281 // struct DEDUCE_EXPR;
282 // #else
283 
284 template<typename R>
285 struct is_key_value_range
286  : conjunction<
287  input_range<R>,
288  has_typename_type<range_key<R>>,
289  has_typename_type<range_mapped<R>>
290  > {};
291 
292 template<template<typename...> class C>
293 struct maybe_key_value_container
294  : conjunction<
295  bool_constant<(mandatory_template_arity<C>::value == 2)>,
296  bool_constant<(template_arity<C>::value > 2)>
297  > {};
298 
299 template<
300  template<typename...> class C,
301  typename R,
302  typename ArgSeq,
303  bool =
304  conjunction<
305  has_typename_type<iter_val<R>>,
306  has_typename_type<iter_key<R>>
307  >::value
308 >
309 struct iter_key_val_category {
310  using category = return_category<0>;
311 };
312 template<template<typename...> class C, typename R, typename... Args>
313 struct iter_key_val_category<C, R, type_sequence<Args...>, true> {
314  using category =
315  std::conditional_t<
316  std::is_constructible<
317  C<iter_key_t<R>, iter_val_t<R>, Args...>,
318  ranges_to_input_iterator<R>&&, ranges_to_input_iterator<R>&&
319  >::value,
320  return_category<2, C<iter_key_t<R>, iter_val_t<R>, Args...>>,
321  return_category<0>
322  >;
323 };
324 
325 template<template<typename...> class C, typename R, typename ArgSeq>
326 struct DEDUCE_EXPR_IMPL_KV;
327 template<template<typename...> class C, typename R, typename... Args>
328 struct DEDUCE_EXPR_IMPL_KV<C, R, type_sequence<Args...>> {
329  using category =
330  std::conditional_t<
331  std::is_constructible<
332  C<range_key_t<R>, range_mapped_t<R>, Args...>,
333  R&&, Args&&...>::value,
334  return_category<1, C<range_key_t<R>, range_mapped_t<R>, Args...>>,
335  std::conditional_t<
336  std::is_constructible<
337  C<range_key_t<R>, range_mapped_t<R>, Args...>,
338  from_range_t, R&&, Args&&...>::value,
339  return_category<1, C<range_key_t<R>, range_mapped_t<R>, Args...>>,
340  std::conditional_t<
341  std::is_constructible<
342  C<range_key_t<R>, range_mapped_t<R>, Args...>,
343  ranges_to_input_iterator<R>&&, ranges_to_input_iterator<R>&&>::value,
344  return_category<1, C<range_key_t<R>, range_mapped_t<R>, Args...>>,
345  typename iter_key_val_category<C, R, type_sequence<Args...>>::category
346  >>>;
347 };
348 
349 template<template<typename...> class C, typename R, typename ArgSeq, bool = has_typename_type<iter_val<R>>::value>
350 struct iter_val_category {
351  using category = return_category<0>;
352 };
353 template<template<typename...> class C, typename R, typename... Args>
354 struct iter_val_category<C, R, type_sequence<Args...>, true> {
355  using category =
356  std::conditional_t<
357  std::is_constructible<
358  C<iter_val_t<std::decay_t<R>>, Args...>,
359  ranges_to_input_iterator<R>&&, ranges_to_input_iterator<R>&&
360  >::value,
361  return_category<2, C<iter_val_t<R>, Args...>>,
362  return_category<0>>;
363 };
364 
365 template<template<typename...> class C, typename R, typename ArgSeq>
366 struct DEDUCE_EXPR_IMPL_T;
367 template<template<typename...> class C, typename R, typename... Args>
368 struct DEDUCE_EXPR_IMPL_T<C, R, type_sequence<Args...>> {
369  using category =
370  std::conditional_t<
371  std::is_constructible<
372  C<range_value_t<R>, Args...>,
373  R&&, Args&&... >::value,
374  return_category<1, C<range_value_t<R>, Args...>>,
375  std::conditional_t<
376  std::is_constructible<
377  C<range_value_t<R>, Args...>,
378  from_range_t, R&&, Args&&... >::value,
379  return_category<1, C<range_value_t<R>, Args...>>,
380  std::conditional_t<
381  std::is_constructible<
382  C<range_value_t<R>, Args...>,
383  ranges_to_input_iterator<R>&&, ranges_to_input_iterator<R>&& >::value,
384  return_category<1, C<range_value_t<R>, Args...>>,
385  typename iter_val_category<C, R, type_sequence<Args...>>::category
386  >>>;
387 };
388 
389 template<
390  template<typename...> class C,
391  typename R,
392  typename ArgSeq,
393  bool =
394  conjunction<
395  maybe_key_value_container<C>,
396  is_key_value_range<R>
397  >::value
398 >
399 struct DEDUCE_EXPR_IMPL;
400 
401 template<template<typename...> class C, typename R, typename ArgSeq>
402 struct DEDUCE_EXPR_IMPL<C, R, ArgSeq, true> : DEDUCE_EXPR_IMPL_KV<C, R, ArgSeq> {};
403 template<template<typename...> class C, typename R, typename ArgSeq>
404 struct DEDUCE_EXPR_IMPL<C, R, ArgSeq, false> : DEDUCE_EXPR_IMPL_T<C, R, ArgSeq> {};
405 
406 template<template<typename...> class C, typename R, typename... Args>
407 using DEDUCE_EXPR_CATEGORY = typename DEDUCE_EXPR_IMPL<C, R, type_sequence<Args...>>::category;
408 
409 // #endif
410 
411 } // namespace detail
412 
439 
441 template<typename C, typename R, typename... Args, std::enable_if_t<conjunction<
442  input_range<R>,
443  negation< view<C> >
444 >::value, int> = 0>
445 constexpr std::enable_if_t<(detail::ranges_to_1_tag<C, R, Args...>::value > 0), C>
446 to(R&& r, Args&&... args) {
447  return detail::to_1<C>(detail::ranges_to_1_tag<C, R, Args...>{}, std::forward<R>(r), std::forward<Args>(args)...);
448 }
449 
451 template<template<typename...> class C, typename R, typename... Args, std::enable_if_t<
452  input_range<R>::value, int> = 0>
453 constexpr typename detail::DEDUCE_EXPR_CATEGORY<C, R, Args...>::return_type
454 to(R&& r, Args&&... args) {
455  using DEDUCE_EXPR = typename detail::DEDUCE_EXPR_CATEGORY<C, R, Args...>::return_type;
456  return vccc::ranges::to<DEDUCE_EXPR>(std::forward<R>(r), std::forward<Args>(args)...);
457 }
458 
459 namespace detail {
460 
461 template<typename C, typename R, typename... Args>
462 constexpr C to_1(tag_5, R&& r, Args&&... args) {
463  return vccc::ranges::to<C>(r | views::transform([](auto&& elem) {
464  return to<range_value_t<C>>(std::forward<decltype(elem)>(elem));
465  }), std::forward<Args>(args)...);
466 }
467 
468 template<typename C, typename... Args>
469 class to_adaptor_closure : public range_adaptor_closure<to_adaptor_closure<C, Args...>> {
470  public:
471  template<typename... T>
472  constexpr explicit to_adaptor_closure(in_place_t, T&&... arg)
473  : tup_(std::forward<T>(arg)...) {}
474 
476  constexpr auto operator()(R&& r) const& {
477  return call(std::forward<R>(r), std::index_sequence_for<Args...>{});
478  }
479 
481  constexpr auto operator()(R&& r) && {
482  return std::move(*this).call(std::forward<R>(r), std::index_sequence_for<Args...>{});
483  }
484 
485  private:
486  template<typename R, std::size_t... I>
487  constexpr auto call(R&& r, std::index_sequence<I...>) const& {
488  return vccc::ranges::to<C>(std::forward<R>(r), std::get<I>(tup_)...);
489  }
490  template<typename R, std::size_t... I>
491  constexpr auto call(R&& r, std::index_sequence<I...>) && {
492  return vccc::ranges::to<C>(std::forward<R>(r), std::get<I>(std::move(tup_))...);
493  }
494 
495  std::tuple<Args...> tup_;
496 };
497 
498 template<template<typename...> class>
499 struct template_type_holder;
500 
501 template<template<typename...> class C, typename... Args>
502 class to_adaptor_closure<template_type_holder<C>, Args...>
503  : public range_adaptor_closure<to_adaptor_closure<template_type_holder<C>, Args...>>
504 {
505  public:
506  template<typename... T>
507  constexpr explicit to_adaptor_closure(in_place_t, T&&... arg)
508  : tup_(std::forward<T>(arg)...) {}
509 
511  constexpr auto operator()(R&& r) const& {
512  return call(std::forward<R>(r), std::index_sequence_for<Args...>{});
513  }
514 
516  constexpr auto operator()(R&& r) && {
517  return std::move(*this).call(std::forward<R>(r), std::index_sequence_for<Args...>{});
518  }
519 
520  private:
521  template<typename R, std::size_t... I>
522  constexpr auto call(R&& r, std::index_sequence<I...>) const& {
523  return vccc::ranges::to<C>(std::forward<R>(r), std::get<I>(tup_)...);
524  }
525  template<typename R, std::size_t... I>
526  constexpr auto call(R&& r, std::index_sequence<I...>) && {
527  return vccc::ranges::to<C>(std::forward<R>(r), std::get<I>(std::move(tup_))...);
528  }
529 
530  std::tuple<Args...> tup_;
531 };
532 
533 template<typename...>
534 struct to_check_arg;
535 template<>
536 struct to_check_arg<> : std::true_type {};
537 template<typename T, typename... U>
538 struct to_check_arg<T, U...> : negation<input_range<T>> {};
539 
540 } // namespace detail
541 
544 template<typename C, typename... Args, std::enable_if_t<conjunction<
545  detail::to_check_arg<Args...>,
546  view<C>
547 >::value == false, int> = 0>
548 constexpr detail::to_adaptor_closure<C, std::decay_t<Args>...> to(Args&&... args) {
549  return detail::to_adaptor_closure<C, std::decay_t<Args>...>(in_place, std::forward<Args>(args)...);
550 }
551 
554 template<template<typename...> class C, typename... Args, std::enable_if_t<
555  detail::to_check_arg<Args...>::value, int> = 0>
556 constexpr detail::to_adaptor_closure<detail::template_type_holder<C>, std::decay_t<Args>...>
557 to(Args&&... args) {
558  return detail::to_adaptor_closure<detail::template_type_holder<C>, std::decay_t<Args>...>(in_place, std::forward<Args>(args)...);
559 }
560 
562 
563 } // namespace ranges
564 } // namespace vccc
565 
566 #endif // VCCC_RANGES_TO_HPP_
constexpr VCCC_INLINE_OR_STATIC detail::copy_niebloid copy
Definition: copy.hpp:69
std::input_iterator_tag input_iterator_tag
Definition: iterator_tag.hpp:15
constexpr MatrixMulMatrix< E1, E2 > operator*(const MatrixBase< E1 > &lhs, const MatrixBase< E2 > &rhs)
Definition: matrix_mul_matrix.hpp:77
constexpr std::enable_if_t<(detail::ranges_to_1_tag< C, R, Args... >::value > 0), C > to(R &&r, Args &&... args)
Constructs an object of type C from the elements of r
Definition: to.hpp:446
constexpr VCCC_INLINE_OR_STATIC detail::transform_niebloid transform
Definition: transform.hpp:61
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 from_range_t from_range
Definition: from_range.hpp:28
constexpr VCCC_INLINE_OR_STATIC detail::end_niebloid end
returns a sentinel indicating the end of a range
Definition: end.hpp:120
void void_t
Definition: void_t.hpp:19
constexpr VCCC_INLINE_OR_STATIC in_place_t in_place
Definition: in_place.hpp:47
Definition: matrix.hpp:495
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35
constexpr bool operator==(const MatrixBase< E1 > &lhs, const MatrixBase< E2 > &rhs)
Definition: mat_expr_operations.hpp:15