14 #ifndef RANGES_V3_VIEW_TRANSFORM_HPP
15 #define RANGES_V3_VIEW_TRANSFORM_HPP
18 #include <type_traits>
36 #include <range/v3/utility/static_const.hpp>
41 #include <range/v3/detail/prologue.hpp>
48 constexpr cardinality transform2_cardinality(cardinality c1, cardinality c2)
50 return c1 >= 0 || c2 >= 0
51 ? (c1 >= 0 && c2 >= 0 ? (c1 < c2 ? c1 : c2) : finite)
52 : c1 == finite || c2 == finite
54 : c1 == unknown || c2 == unknown ? unknown : infinite;
60 template(
typename Fun,
typename Rng)(
61 concept (iter_transform_1_readable_)(Fun, Rng),
65 common_reference_with<
66 invoke_result_t<Fun &, iterator_t<Rng>> &&,
67 invoke_result_t<Fun &, copy_tag, iterator_t<Rng>> &> AND
68 common_reference_with<
69 invoke_result_t<Fun &, iterator_t<Rng>> &&,
70 invoke_result_t<Fun &, move_tag, iterator_t<Rng>> &&> AND
71 common_reference_with<
72 invoke_result_t<Fun &, move_tag, iterator_t<Rng>> &&,
73 invoke_result_t<Fun &, copy_tag, iterator_t<Rng>>
const &>
77 template<
typename Fun,
typename Rng>
78 CPP_concept iter_transform_1_readable =
79 CPP_concept_ref(detail::iter_transform_1_readable_, Fun, Rng);
83 template(
typename Fun,
typename Rng1,
typename Rng2)(
84 concept (iter_transform_2_readable_)(Fun, Rng1, Rng2),
88 common_reference_with<
89 invoke_result_t<Fun &, iterator_t<Rng1>, iterator_t<Rng2>> &&,
90 invoke_result_t<Fun &, copy_tag, iterator_t<Rng1>, iterator_t<Rng2>> &> AND
91 common_reference_with<
92 invoke_result_t<Fun &, iterator_t<Rng1>, iterator_t<Rng2>> &&,
93 invoke_result_t<Fun &, move_tag, iterator_t<Rng1>, iterator_t<Rng2>> &&> AND
94 common_reference_with<
95 invoke_result_t<Fun &, move_tag, iterator_t<Rng1>, iterator_t<Rng2>> &&,
96 invoke_result_t<Fun &, copy_tag, iterator_t<Rng1>, iterator_t<Rng2>>
const &>
100 template<
typename Fun,
typename Rng1,
typename Rng2>
101 CPP_concept iter_transform_2_readable =
102 CPP_concept_ref(detail::iter_transform_2_readable_, Fun, Rng1, Rng2);
109 template<
typename Rng,
typename Fun>
114 RANGES_NO_UNIQUE_ADDRESS semiregular_box_t<Fun> fun_;
116 using use_sentinel_t =
118 single_pass_iterator_<iterator_t<meta::const_if_c<Const, Rng>>>>;
120 template<
bool IsConst>
124 friend struct adaptor<!IsConst>;
125 using CRng = meta::const_if_c<IsConst, Rng>;
126 using fun_ref_ = semiregular_box_ref_or_val_t<Fun, IsConst>;
127 RANGES_NO_UNIQUE_ADDRESS fun_ref_ fun_;
131 detail::decay_t<invoke_result_t<Fun &, copy_tag, iterator_t<CRng>>>;
133 adaptor(fun_ref_ fun)
134 : fun_(std::move(fun))
136 template(
bool Other)(
137 requires IsConst AND CPP_NOT(Other))
138 adaptor(adaptor<Other> that)
139 : fun_(std::move(that.fun_))
154 adaptor<false> begin_adaptor()
158 template(
bool Const =
true)(
159 requires Const AND
range<meta::const_if_c<Const, Rng>> AND
160 detail::iter_transform_1_readable<Fun
const,
161 meta::const_if_c<Const, Rng>>)
162 adaptor<Const> begin_adaptor()
const
170 template(
bool Const =
true)(
171 requires Const AND
range<meta::const_if_c<Const, Rng>> AND
172 detail::iter_transform_1_readable<Fun
const,
173 meta::const_if_c<Const, Rng>>)
182 : iter_transform_view::view_adaptor{std::move(rng)}
183 , fun_(std::move(fun))
186 constexpr
auto CPP_fun(
size)()(
187 requires sized_range<Rng>)
192 constexpr
auto CPP_fun(
size)()(
const
193 requires sized_range<Rng const>)
199 template<
typename Rng,
typename Fun>
205 indirect(std::move(fun))}
209 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
210 template(
typename Rng,
typename Fun)(
211 requires copy_constructible<Fun>)
216 template<
typename Rng1,
typename Rng2,
typename Fun>
218 :
view_facade<iter_transform2_view<Rng1, Rng2, Fun>,
219 detail::transform2_cardinality(range_cardinality<Rng1>::value,
220 range_cardinality<Rng2>::value)>
224 RANGES_NO_UNIQUE_ADDRESS semiregular_box_t<Fun> fun_;
227 using difference_type_ =
228 common_type_t<range_difference_t<Rng1>, range_difference_t<Rng2>>;
230 static constexpr cardinality my_cardinality = detail::transform2_cardinality(
240 friend struct cursor<Const>;
241 sentinel_t<meta::const_if_c<Const, Rng1>> end1_;
242 sentinel_t<meta::const_if_c<Const, Rng2>> end2_;
245 sentinel() =
default;
246 sentinel(meta::const_if_c<Const, iter_transform2_view> * parent,
247 decltype(ranges::end))
248 : end1_(end(parent->rng1_))
249 , end2_(end(parent->rng2_))
251 template(
bool Other)(
252 requires Const AND CPP_NOT(Other))
253 sentinel(sentinel<Other> that)
254 : end1_(std::move(that.end1_))
255 , end2_(std::move(that.end2_))
263 using fun_ref_ = semiregular_box_ref_or_val_t<Fun, Const>;
264 using R1 = meta::const_if_c<Const, Rng1>;
265 using R2 = meta::const_if_c<Const, Rng2>;
271 using difference_type = difference_type_;
273 (
bool)single_pass_iterator_<iterator_t<R2>>>;
275 detail::decay_t<invoke_result_t<meta::const_if_c<Const, Fun> &,
copy_tag,
279 template<
typename BeginEndFn>
280 cursor(meta::const_if_c<Const, iter_transform2_view> * parent,
281 BeginEndFn begin_end)
283 , it1_(begin_end(parent->rng1_))
284 , it2_(begin_end(parent->rng2_))
286 template(
bool Other)(
287 requires Const AND CPP_NOT(Other))
288 cursor(cursor<Other> that)
289 : fun_(std::move(that.fun_))
290 , it1_(std::move(that.end1_))
291 , it2_(std::move(that.end2_))
294 auto CPP_auto_fun(read)()(
const)
296 return invoke(fun_, it1_, it2_)
305 auto equal(cursor
const & that)
const
307 requires forward_range<Rng1> && forward_range<Rng2>)
312 return it1_ == that.it1_ || it2_ == that.it2_;
314 bool equal(sentinel<Const>
const & s)
const
319 return it1_ == s.end1_ || it2_ == s.end2_;
324 requires bidirectional_range<R1> && bidirectional_range<R2>)
330 auto advance(difference_type n) -> CPP_ret(
void)(
331 requires random_access_range<R1> && random_access_range<R2>)
333 ranges::advance(it1_, n);
334 ranges::advance(it2_, n);
337 auto distance_to(cursor
const & that)
const
338 -> CPP_ret(difference_type)(
344 difference_type d1 = that.it1_ - it1_, d2 = that.it2_ - it2_;
345 return 0 < d1 ? ranges::min(d1, d2) : ranges::max(d1, d2);
348 auto CPP_auto_fun(move)()(
const)
356 using end_cursor_t = meta::if_c<
357 common_range<meta::const_if_c<Const, Rng1>> &&
358 common_range<meta::const_if_c<Const, Rng2>> &&
359 !single_pass_iterator_<iterator_t<meta::const_if_c<Const, Rng1>>> &&
360 !single_pass_iterator_<iterator_t<meta::const_if_c<Const, Rng2>>>,
361 cursor<Const>, sentinel<Const>>;
363 cursor<simple_view<Rng1>() && simple_view<Rng2>()> begin_cursor()
365 return {
this, ranges::begin};
367 end_cursor_t<simple_view<Rng1>() && simple_view<Rng2>()> end_cursor()
369 return {
this, ranges::end};
371 template(
bool Const =
true)(
372 requires Const AND
range<meta::const_if_c<Const, Rng1>> AND
373 range<meta::const_if_c<Const, Rng2>> AND
374 detail::iter_transform_2_readable<
376 meta::const_if_c<Const, Rng1>,
377 meta::const_if_c<Const, Rng2>>)
378 cursor<true> begin_cursor()
const
380 return {
this, ranges::begin};
382 template(
bool Const =
true)(
383 requires Const AND
range<meta::const_if_c<Const, Rng1>> AND
384 range<meta::const_if_c<Const, Rng2>> AND
385 detail::iter_transform_2_readable<
387 meta::const_if_c<Const, Rng1>,
388 meta::const_if_c<Const, Rng2>>)
389 end_cursor_t<Const> end_cursor()
const
391 return {
this, ranges::end};
393 template<
typename Self>
394 static constexpr
auto size_(Self &
self)
396 using size_type = common_type_t<range_size_t<Rng1>, range_size_t<Rng2>>;
397 return ranges::min(
static_cast<size_type
>(
ranges::size(
self.rng1_)),
409 : fun_(std::move(fun))
410 , rng1_(std::move(rng1))
411 , rng2_(std::move(rng2))
414 static constexpr
auto size()
416 requires (my_cardinality >= 0))
420 template(
bool True =
true)(
421 requires (my_cardinality < 0) AND sized_range<Rng1 const> AND
422 sized_range<Rng2 const> AND
423 common_with<range_size_t<R1<True>>, range_size_t<R2<True>>>)
424 constexpr
auto size()
const
428 template(
bool True =
true)(
429 requires (my_cardinality < 0) AND sized_range<Rng1> AND sized_range<Rng2> AND
430 common_with<range_size_t<R1<True>>, range_size_t<R2<True>>>)
431 constexpr
auto size()
437 template<
typename Rng1,
typename Rng2,
typename Fun>
444 indirect(std::move(fun))}
452 template(
typename Rng,
typename Fun)(
453 requires viewable_range<Rng> AND input_range<Rng> AND
454 copy_constructible<Fun> AND
455 detail::iter_transform_1_readable<Fun, Rng>)
457 operator()(Rng && rng, Fun fun)
const
459 return {all(
static_cast<Rng &&
>(rng)), std::move(fun)};
462 template(
typename Rng1,
typename Rng2,
typename Fun)(
463 requires viewable_range<Rng1> AND input_range<Rng1> AND
464 viewable_range<Rng2> AND input_range<Rng2> AND
465 copy_constructible<Fun> AND
466 common_with<range_difference_t<Rng1>, range_difference_t<Rng1>> AND
467 detail::iter_transform_2_readable<Fun, Rng1, Rng2>)
469 operator()(Rng1 && rng1, Rng2 && rng2, Fun fun)
const
471 return {all(
static_cast<Rng1 &&
>(rng1)),
472 all(
static_cast<Rng2 &&
>(rng2)),
479 using iter_transform_base_fn::operator();
481 template<
typename Fun>
482 constexpr
auto operator()(Fun fun)
const
484 return make_view_closure(
499 concept (transformable_range_)(Rng, Fun),
501 (!std::is_void<indirect_result_t<Fun &,
iterator_t<Rng>>>::value)
505 template<typename Rng, typename Fun>
508 copy_constructible<Fun> &&
509 CPP_concept_ref(views::transformable_range_, Rng, Fun);
513 template(typename Rng1, typename Rng2, typename Fun)(
514 concept (transformable_ranges_)(Rng1, Rng2, Fun),
521 template<typename Rng1, typename Rng2, typename Fun>
525 copy_constructible<Fun> &&
526 CPP_concept_ref(views::transformable_ranges_, Rng1, Rng2, Fun);
531 template(
typename Rng,
typename Fun)(
532 requires transformable_range<Rng, Fun>)
536 return {all(
static_cast<Rng &&
>(rng)), std::move(fun)};
539 template(
typename Rng1,
typename Rng2,
typename Fun)(
540 requires transformable_ranges<Rng1, Rng2, Fun>)
542 operator()(Rng1 && rng1, Rng2 && rng2, Fun fun)
const
544 return {all(
static_cast<Rng1 &&
>(rng1)),
545 all(
static_cast<Rng2 &&
>(rng2)),
583 using transform_base_fn::operator();
585 template<
typename Fun>
586 constexpr
auto operator()(Fun fun)
const
601 using ranges::views::transform;
603 template(
typename Rng,
typename F)(
604 requires input_range<Rng> AND copy_constructible<F> AND view_<Rng> AND
605 std::is_object<F>::value AND
612 #include <range/v3/detail/epilogue.hpp>
614 #include <range/v3/detail/satisfy_boost_range.hpp>
CPP_concept regular_invocable
\concept regular_invocable
Definition: concepts.hpp:55
CPP_concept input_range
\concept input_range
Definition: concepts.hpp:103
CPP_concept viewable_range
\concept viewable_range
Definition: concepts.hpp:260
CPP_concept range
\concept range
Definition: concepts.hpp:69
decltype(begin(declval(Rng &))) iterator_t
Definition: access.hpp:698
RANGES_INLINE_VARIABLE(detail::to_container_fn< detail::from_range< std::vector >>, to_vector) template< template< typename... > class ContT > auto to(RANGES_HIDDEN_DETAIL(detail
For initializing a container of the specified type with the elements of an Range.
Definition: conversion.hpp:399
std::integral_constant< bool, B > bool_
An integral constant wrapper for bool.
Definition: meta.hpp:168
std::integral_constant< std::size_t, N > size_t
An integral constant wrapper for std::size_t.
Definition: meta.hpp:163
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition: meta.hpp:541
defer< bind_back, Fn, Ts... > bind_back
Definition: meta.hpp:994
meta::size_t< L::size()> size
An integral constant wrapper that is the size of the meta::list L.
Definition: meta.hpp:1696
_t< detail::_if_< list< Args... > >> if_
Select one type or another depending on a compile-time Boolean.
Definition: meta.hpp:1247
CPP_concept transformable_ranges
\concept transformable_ranges
Definition: transform.hpp:522
CPP_concept transformable_range
\concept transformable_range
Definition: transform.hpp:506
template(typename Rng1, typename Rng2, typename Fun)(concept(transformable_ranges_)(Rng1
\concept transformable_ranges_
Definition: adaptor.hpp:110
Definition: range_fwd.hpp:492
Definition: range_fwd.hpp:494
Definition: traits.hpp:128
Definition: adaptor.hpp:475
A utility for constructing a view from a (derived) type that implements begin and end cursors.
Definition: facade.hpp:66