File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/XS/librangeV3.x/i/range/v3/view/transform.hpp
Criterion Covered Total %
statement 21 21 100.0
branch 5 10 50.0
condition n/a
subroutine n/a
pod n/a
total 26 31 83.8


line stmt bran cond sub pod time code
1             /// \file
2             // Range v3 library
3             //
4             // Copyright Eric Niebler 2013-present
5             //
6             // Use, modification and distribution is subject to the
7             // Boost Software License, Version 1.0. (See accompanying
8             // file LICENSE_1_0.txt or copy at
9             // http://www.boost.org/LICENSE_1_0.txt)
10             //
11             // Project home: https://github.com/ericniebler/range-v3
12             //
13              
14             #ifndef RANGES_V3_VIEW_TRANSFORM_HPP
15             #define RANGES_V3_VIEW_TRANSFORM_HPP
16              
17             #include
18             #include
19             #include
20             #include
21             #include
22             #include
23             #include
24             #include
25             #include
26             #include
27             #include
28             #include
29             #include
30             #include
31             #include
32             #include
33             #include
34             #include
35              
36             namespace ranges
37             {
38             inline namespace v3
39             {
40             /// \cond
41             namespace detail
42             {
43             constexpr cardinality transform2_cardinality(cardinality c1, cardinality c2)
44             {
45             return c1 >= 0 || c2 >= 0 ?
46             (c1 >= 0 && c2 >= 0 ? (c1 < c2 ? c1 : c2) : finite) :
47             c1 == finite || c2 == finite ?
48             finite :
49             c1 == unknown || c2 == unknown ?
50             unknown :
51             infinite;
52             }
53             }
54             /// \endcond
55              
56             /// \addtogroup group-views
57             /// @{
58             template
59             struct iter_transform_view
60             : view_adaptor, Rng>
61             {
62             private:
63             friend range_access;
64             semiregular_t fun_;
65             using use_sentinel_t =
66             meta::or_>, SinglePass>>;
67              
68             template
69             struct adaptor : adaptor_base
70             {
71             private:
72             friend struct adaptor;
73             using CRng = meta::const_if_c;
74             using fun_ref_ = semiregular_ref_or_val_t;
75             fun_ref_ fun_;
76             public:
77             using value_type =
78             detail::decay_t>>;
79             adaptor() = default;
80 638           adaptor(fun_ref_ fun)
81 638           : fun_(std::move(fun))
82 638           {}
83             template
84             CONCEPT_REQUIRES_(IsConst && (!Other))>
85             adaptor(adaptor that)
86             : fun_(std::move(that.fun_))
87             {}
88 154           auto read(iterator_t it) const
89 154           RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
90             (
91             invoke(fun_, it)
92             )
93             auto iter_move(iterator_t it) const
94             RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
95             (
96             invoke(fun_, move_tag{}, it)
97             )
98             };
99              
100 319           adaptor begin_adaptor()
101             {
102 319           return {fun_};
103             }
104             template
105             CONCEPT_REQUIRES_(Range() && Invocable>())>
106             adaptor begin_adaptor() const
107             {
108             return {fun_};
109             }
110 319           meta::if_> end_adaptor()
111             {
112 319           return {fun_};
113             }
114             template
115             CONCEPT_REQUIRES_(Range() && Invocable>())>
116             meta::if_> end_adaptor() const
117             {
118             return {fun_};
119             }
120             public:
121             iter_transform_view() = default;
122 319           iter_transform_view(Rng rng, Fun fun)
123 319           : iter_transform_view::view_adaptor{std::move(rng)}
124 319           , fun_(std::move(fun))
125 319           {}
126             CONCEPT_REQUIRES(SizedRange())
127             constexpr range_size_type_t size() const
128             {
129             return static_cast>(ranges::size(this->base()));
130             }
131             CONCEPT_REQUIRES(SizedRange())
132             RANGES_CXX14_CONSTEXPR range_size_type_t size()
133             {
134             return static_cast>(ranges::size(this->base()));
135             }
136             };
137              
138             template
139             struct transform_view
140             : iter_transform_view>
141             {
142             transform_view() = default;
143 319           transform_view(Rng rng, Fun fun)
144 319           : iter_transform_view>{std::move(rng),
145 319 50         indirect(std::move(fun))}
    50          
146 319           {}
147             };
148              
149             template
150             struct iter_transform2_view
151             : view_facade<
152             iter_transform2_view,
153             detail::transform2_cardinality(
154             range_cardinality::value,
155             range_cardinality::value)>
156             {
157             private:
158             friend range_access;
159             semiregular_t fun_;
160             Rng1 rng1_;
161             Rng2 rng2_;
162             using difference_type_ = common_type_t, range_difference_type_t>;
163             using size_type_ = meta::_t>;
164              
165             static constexpr cardinality my_cardinality = detail::transform2_cardinality(
166             range_cardinality::value,
167             range_cardinality::value);
168              
169             template
170             struct cursor;
171              
172             template
173             struct sentinel
174             {
175             private:
176             friend struct cursor;
177             sentinel_t> end1_;
178             sentinel_t> end2_;
179             public:
180             sentinel() = default;
181             sentinel(meta::const_if_c &parent, decltype(end))
182             : end1_(end(parent.rng1_)), end2_(end(parent.rng2_))
183             {}
184             template
185             sentinel(sentinel that)
186             : end1_(std::move(that.end1_))
187             , end2_(std::move(that.end2_))
188             {}
189             };
190              
191             template
192             struct cursor
193             {
194             private:
195             using fun_ref_ = semiregular_ref_or_val_t;
196             using R1 = meta::const_if_c;
197             using R2 = meta::const_if_c;
198             fun_ref_ fun_;
199             iterator_t it1_;
200             iterator_t it2_;
201              
202             public:
203             using difference_type = difference_type_;
204             using single_pass = meta::or_c<
205             (bool) SinglePass>(),
206             (bool) SinglePass>()>;
207             using value_type =
208             detail::decay_t<
209             invoke_result_t<
210             meta::const_if_c &,
211             copy_tag,
212             iterator_t,
213             iterator_t>>;
214              
215             cursor() = default;
216             template
217             cursor(meta::const_if_c &parent, BeginEndFn begin_end)
218             : fun_(parent.fun_), it1_(begin_end(parent.rng1_)), it2_(begin_end(parent.rng2_))
219             {}
220             template
221             cursor(cursor that)
222             : fun_(std::move(that.fun_))
223             , it1_(std::move(that.end1_))
224             , it2_(std::move(that.end2_))
225             {}
226             auto read() const
227             RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
228             (
229             invoke(fun_, it1_, it2_)
230             )
231             void next()
232             {
233             ++it1_;
234             ++it2_;
235             }
236             bool equal(cursor const &that) const
237             {
238             // By returning true if *any* of the iterators are equal, we allow
239             // transformed ranges to be of different lengths, stopping when the first
240             // one reaches the end.
241             return it1_ == that.it1_ || it2_ == that.it2_;
242             }
243             bool equal(sentinel const &s) const
244             {
245             // By returning true if *any* of the iterators are equal, we allow
246             // transformed ranges to be of different lengths, stopping when the first
247             // one reaches the end.
248             return it1_ == s.end1_ || it2_ == s.end2_;
249             }
250             CONCEPT_REQUIRES(BidirectionalRange() && BidirectionalRange())
251             void prev()
252             {
253             --it1_;
254             --it2_;
255             }
256             CONCEPT_REQUIRES(RandomAccessRange() && RandomAccessRange())
257             void advance(difference_type n)
258             {
259             ranges::advance(it1_, n);
260             ranges::advance(it2_, n);
261             }
262             CONCEPT_REQUIRES(
263             SizedSentinel, iterator_t>() &&
264             SizedSentinel, iterator_t>())
265             difference_type distance_to(cursor const &that) const
266             {
267             // Return the smallest distance (in magnitude) of any of the iterator
268             // pairs. This is to accommodate zippers of sequences of different length.
269             difference_type d1 = that.it1_ - it1_, d2 = that.it2_ - it2_;
270             return 0 < d1 ? ranges::min(d1, d2) : ranges::max(d1, d2);
271             }
272             auto move() const
273             RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
274             (
275             invoke(fun_, move_tag{}, it1_, it2_)
276             )
277             };
278              
279             template
280             using end_cursor_t =
281             meta::if_c<
282             BoundedRange>() &&
283             BoundedRange>() &&
284             !SinglePass>>() &&
285             !SinglePass>>(),
286             cursor,
287             sentinel>;
288              
289             cursor() && simple_view()>
290             begin_cursor()
291             {
292             return {*this, ranges::begin};
293             }
294             end_cursor_t() && simple_view()> end_cursor()
295             {
296             return {*this, ranges::end};
297             }
298             template
299             CONCEPT_REQUIRES_(Range() && Range() &&
300             IndirectInvocable, iterator_t>())>
301             cursor begin_cursor() const
302             {
303             return {*this, ranges::begin};
304             }
305             template
306             CONCEPT_REQUIRES_(Range() && Range() &&
307             IndirectInvocable, iterator_t>())>
308             end_cursor_t end_cursor() const
309             {
310             return {*this, ranges::end};
311             }
312             template
313             static constexpr size_type_ size_(Self& self)
314             {
315             return ranges::min(
316             static_cast(ranges::size(self.rng1_)),
317             static_cast(ranges::size(self.rng2_)));
318             }
319             public:
320             iter_transform2_view() = default;
321             iter_transform2_view(Rng1 rng1, Rng2 rng2, Fun fun)
322             : fun_(std::move(fun))
323             , rng1_(std::move(rng1))
324             , rng2_(std::move(rng2))
325             {}
326             CONCEPT_REQUIRES(my_cardinality >= 0)
327             constexpr size_type_ size() const
328             {
329             return static_cast(my_cardinality);
330             }
331             CONCEPT_REQUIRES(my_cardinality < 0 &&
332             SizedRange() && SizedRange())
333             constexpr size_type_ size() const
334             {
335             return size_(*this);
336             }
337             CONCEPT_REQUIRES(my_cardinality < 0 &&
338             SizedRange() && SizedRange())
339             RANGES_CXX14_CONSTEXPR size_type_ size()
340             {
341             return size_(*this);
342             }
343             };
344              
345             template
346             struct transform2_view
347             : iter_transform2_view>
348             {
349             transform2_view() = default;
350             transform2_view(Rng1 rng1, Rng2 rng2, Fun fun)
351             : iter_transform2_view>{std::move(rng1),
352             std::move(rng2), indirect(std::move(fun))}
353             {}
354             };
355              
356             namespace view
357             {
358             struct iter_transform_fn
359             {
360             private:
361             friend view_access;
362             template
363             static auto bind(iter_transform_fn iter_transform, Fun fun)
364             RANGES_DECLTYPE_AUTO_RETURN
365             (
366             make_pipeable(std::bind(iter_transform, std::placeholders::_1,
367             protect(std::move(fun))))
368             )
369             public:
370             template
371             using Concept = meta::and_<
372             InputRange,
373             CopyConstructible,
374             Invocable>,
375             Invocable>,
376             Invocable>>;
377              
378             template
379             using Concept2 = meta::and_<
380             InputRange,
381             InputRange,
382             CopyConstructible,
383             Invocable, iterator_t>,
384             Invocable, iterator_t>,
385             Invocable, iterator_t>>;
386              
387             template
388             CONCEPT_REQUIRES_(Concept())>
389             iter_transform_view, Fun> operator()(Rng && rng, Fun fun) const
390             {
391             return {all(static_cast(rng)), std::move(fun)};
392             }
393              
394             template
395             CONCEPT_REQUIRES_(Concept2())>
396             iter_transform2_view, all_t, Fun>
397             operator()(Rng1 && rng1, Rng2 && rng2, Fun fun) const
398             {
399             return {all(static_cast(rng1)), all(static_cast(rng2)), std::move(fun)};
400             }
401              
402             #ifndef RANGES_DOXYGEN_INVOKED
403             template
404             CONCEPT_REQUIRES_(!Concept())>
405             void operator()(Rng &&, Fun) const
406             {
407             CONCEPT_ASSERT_MSG(InputRange(),
408             "The object on which view::iter_transform operates must be a model of the "
409             "InputRange concept.");
410             CONCEPT_ASSERT_MSG(
411             CopyConstructible(),
412             "The function passed to view::iter_transform must be CopyConstructible.");
413             CONCEPT_ASSERT_MSG(
414             Invocable>(),
415             "The function passed to view::iter_transform must be callable with an argument "
416             "of the range's iterator type.");
417             CONCEPT_ASSERT_MSG(
418             Invocable>(),
419             "The function passed to view::iter_transform must be callable with "
420             "copy_tag and an argument of the range's iterator type.");
421             CONCEPT_ASSERT_MSG(
422             Invocable>(),
423             "The function passed to view::iter_transform must be callable with "
424             "move_tag and an argument of the range's iterator type.");
425             }
426              
427             template
428             CONCEPT_REQUIRES_(!Concept2())>
429             void operator()(Rng1 &&, Rng2 &&, Fun) const
430             {
431             CONCEPT_ASSERT_MSG(InputRange(),
432             "The first object on which view::iter_transform operates must be a model of the "
433             "InputRange concept.");
434             CONCEPT_ASSERT_MSG(InputRange(),
435             "The second object on which view::iter_transform operates must be a model of the "
436             "InputRange concept.");
437             CONCEPT_ASSERT_MSG(
438             CopyConstructible(),
439             "The function passed to view::iter_transform must be CopyConstructible.");
440             CONCEPT_ASSERT_MSG(
441             Invocable, iterator_t>(),
442             "The function passed to view::iter_transform must be callable with argument "
443             "of the ranges' iterator types.");
444             CONCEPT_ASSERT_MSG(
445             Invocable, iterator_t>(),
446             "The function passed to view::iter_transform must be callable with "
447             "copy_tag and arguments of the ranges' iterator types.");
448             CONCEPT_ASSERT_MSG(
449             Invocable, iterator_t>(),
450             "The function passed to view::iter_transform must be callable with "
451             "move_tag and arguments of the rangess iterator types.");
452             }
453             #endif
454             };
455              
456             /// \relates iter_transform_fn
457             /// \ingroup group-views
458             RANGES_INLINE_VARIABLE(view, iter_transform)
459              
460             struct transform_fn
461             {
462             private:
463             friend view_access;
464             template
465 319           static auto bind(transform_fn transform, Fun fun)
466 319 50         RANGES_DECLTYPE_AUTO_RETURN
    50          
467             (
468             make_pipeable(std::bind(transform, std::placeholders::_1,
469             protect(std::move(fun))))
470             )
471             public:
472             // Don't forget to update view::for_each whenever this set
473             // of concepts changes
474             template
475             using Concept = meta::and_<
476             InputRange,
477             CopyConstructible,
478             Invocable>,
479             meta::not_
480             Fun&, range_reference_t>>>>;
481              
482             template
483             using Concept2 = meta::and_<
484             InputRange,
485             InputRange,
486             CopyConstructible,
487             Invocable, range_reference_t>,
488             meta::not_
489             Fun&, range_reference_t, range_reference_t>>>>;
490              
491             template
492             CONCEPT_REQUIRES_(Concept())>
493 319           transform_view, Fun> operator()(Rng && rng, Fun fun) const
494             {
495 319 50         return {all(static_cast(rng)), std::move(fun)};
496             }
497              
498             template
499             CONCEPT_REQUIRES_(Concept2())>
500             transform2_view, all_t, Fun>
501             operator()(Rng1 && rng1, Rng2 && rng2, Fun fun) const
502             {
503             return {all(static_cast(rng1)), all(static_cast(rng2)),
504             std::move(fun)};
505             }
506              
507             #ifndef RANGES_DOXYGEN_INVOKED
508             template
509             CONCEPT_REQUIRES_(!Concept())>
510             void operator()(Rng &&, Fun) const
511             {
512             CONCEPT_ASSERT_MSG(InputRange(),
513             "The object on which view::transform operates must be a model of the "
514             "InputRange concept.");
515             CONCEPT_ASSERT_MSG(
516             CopyConstructible(),
517             "The function passed to view::transform must be CopyConstructible.");
518             CONCEPT_ASSERT_MSG(
519             Invocable>(),
520             "The function passed to view::transform must be callable with an argument "
521             "of the range's reference type.");
522             CONCEPT_ASSERT_MSG(
523             meta::not_
524             Fun&, range_reference_t>>>(),
525             "The function passed to view::transform must return non-void when called "
526             "with an argument of the range's reference type.");
527             }
528              
529             template
530             CONCEPT_REQUIRES_(!Concept2())>
531             void operator()(Rng1 &&, Rng2 &&, Fun) const
532             {
533             CONCEPT_ASSERT_MSG(InputRange(),
534             "The first object on which view::transform operates must be a model of the "
535             "InputRange concept.");
536             CONCEPT_ASSERT_MSG(InputRange(),
537             "The second object on which view::transform operates must be a model of the "
538             "InputRange concept.");
539             CONCEPT_ASSERT_MSG(
540             CopyConstructible(),
541             "The function passed to view::transform must be CopyConstructible.");
542             CONCEPT_ASSERT_MSG(
543             Invocable, range_reference_t>(),
544             "The function passed to view::transform must be callable with arguments "
545             "of the ranges' reference types.");
546             CONCEPT_ASSERT_MSG(
547             meta::not_
548             Fun&, range_reference_t, range_reference_t>>>(),
549             "The function passed to view::transform must return non-void when called "
550             "with arguments of the ranges' reference types.");
551             }
552             #endif
553             };
554              
555             /// \relates transform_fn
556             /// \ingroup group-views
557             RANGES_INLINE_VARIABLE(view, transform)
558             }
559             /// @}
560             }
561             }
562              
563             RANGES_SATISFY_BOOST_RANGE(::ranges::v3::iter_transform_view)
564             RANGES_SATISFY_BOOST_RANGE(::ranges::v3::transform_view)
565              
566             #endif