File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/XS/librangeV3.x/i/range/v3/utility/functional.hpp
Criterion Covered Total %
statement 26 26 100.0
branch n/a
condition n/a
subroutine n/a
pod n/a
total 26 26 100.0


line stmt bran cond sub pod time code
1             /// \file
2             // Range v3 library
3             //
4             // Copyright Eric Niebler 2013-present
5             // Copyright Casey Carter 2016
6             //
7             // Use, modification and distribution is subject to the
8             // Boost Software License, Version 1.0. (See accompanying
9             // file LICENSE_1_0.txt or copy at
10             // http://www.boost.org/LICENSE_1_0.txt)
11             //
12             // Project home: https://github.com/ericniebler/range-v3
13             //
14             #ifndef RANGES_V3_UTILITY_FUNCTIONAL_HPP
15             #define RANGES_V3_UTILITY_FUNCTIONAL_HPP
16              
17             #include // std::reference_wrapper
18             #include
19             #include // std::addressof
20             #include
21             #include
22             #include
23             #include
24             #include
25             #include
26             #include
27             #include
28             #include
29             #include
30             #include
31              
32             RANGES_DISABLE_WARNINGS
33              
34             namespace ranges
35             {
36             inline namespace v3
37             {
38             /// \addtogroup group-utility
39             /// @{
40             struct equal_to
41             {
42             template
43             CONCEPT_REQUIRES_(EqualityComparable())>
44             constexpr bool operator()(T && t, U && u) const
45             {
46             return (T &&) t == (U &&) u;
47             }
48             using is_transparent = void;
49             };
50              
51             struct not_equal_to
52             {
53             template
54             CONCEPT_REQUIRES_(EqualityComparable())>
55             constexpr bool operator()(T && t, U && u) const
56             {
57             return (T &&) t != (U &&) u;
58             }
59             using is_transparent = void;
60             };
61              
62             struct less
63             {
64             template
65             CONCEPT_REQUIRES_(WeaklyOrdered())>
66             constexpr bool operator()(T && t, U && u) const
67             {
68             return (T &&) t < (U &&) u;
69             }
70             using is_transparent = void;
71             };
72              
73             struct ordered_less
74             {
75             template
76             CONCEPT_REQUIRES_(TotallyOrdered())>
77             constexpr bool operator()(T && t, U && u) const
78             {
79             return (T &&) t < (U &&) u;
80             }
81             using is_transparent = void;
82             };
83              
84             struct ident
85             {
86             template
87             constexpr
88             T && operator()(T && t) const noexcept
89             {
90             return (T &&) t;
91             }
92             using is_transparent = void;
93             };
94              
95             struct plus
96             {
97             template
98             constexpr
99             auto operator()(T && t, U && u) const ->
100             decltype((T &&) t + (U &&) u)
101             {
102             return (T &&) t + (U &&) u;
103             }
104             using is_transparent = void;
105             };
106              
107             struct minus
108             {
109             template
110             constexpr
111             auto operator()(T && t, U && u) const ->
112             decltype((T &&) t - (U &&) u)
113             {
114             return (T &&) t - (U &&) u;
115             }
116             using is_transparent = void;
117             };
118              
119             struct multiplies
120             {
121             template
122             constexpr
123             auto operator()(T && t, U && u) const ->
124             decltype((T &&) t * (U &&) u)
125             {
126             return (T &&) t * (U &&) u;
127             }
128             using is_transparent = void;
129             };
130              
131             struct bitwise_or
132             {
133             template
134             constexpr
135             auto operator()(T && t, U && u) const ->
136             decltype((T &&) t | (U &&) u)
137             {
138             return (T &&) t | (U &&) u;
139             }
140             using is_transparent = void;
141             };
142              
143             template
144             struct convert_to
145             {
146             template
147             constexpr auto operator()(U && u) const
148             RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
149             (
150             static_cast((U &&) u)
151             )
152             };
153              
154             template
155             struct coerce
156             {
157             constexpr
158             T & operator()(T & t) const
159             {
160             return t;
161             }
162             /// \overload
163             constexpr
164             T const & operator()(T const & t) const
165             {
166             return t;
167             }
168             /// \overload
169             constexpr
170             T operator()(T && t) const
171             {
172             return (T &&) t;
173             }
174             T operator()(T const &&) const = delete;
175             };
176              
177             template
178             struct coerce
179             : coerce
180             {};
181              
182             template
183             struct coerce
184             : coerce
185             {};
186              
187             template
188             struct coerce
189             : coerce
190             {};
191              
192             struct dereference_fn
193             {
194             template
195             constexpr auto operator()(I &i) const
196             RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
197             (
198             *i
199             )
200             };
201             RANGES_INLINE_VARIABLE(dereference_fn, dereference)
202              
203             /// \addtogroup group-concepts
204             /// @{
205             namespace concepts
206             {
207             struct Invocable
208             {
209             template
210             using result_t = invoke_result_t;
211              
212             template
213             auto requires_() ->
214             meta::void_>;
215             };
216              
217             struct RegularInvocable
218             : refines
219             {
220             // Axiom: equality_preserving(invoke(f, args...))
221             };
222              
223             struct Predicate
224             : refines
225             {
226             template
227             auto requires_() -> decltype(
228             concepts::valid_expr(
229             concepts::model_of, bool>()
230             ));
231             };
232              
233             struct Relation
234             {
235             template
236             auto requires_() -> decltype(
237             concepts::valid_expr(
238             concepts::model_of()
239             ));
240              
241             template
242             auto requires_() -> decltype(
243             concepts::valid_expr(
244             concepts::is_true(std::is_same{}),
245             concepts::model_of()
246             ));
247              
248             template
249             typename C =
250             common_reference_t, detail::as_cref_t>>
251             auto requires_() -> decltype(
252             concepts::valid_expr(
253             concepts::is_false(std::is_same{}),
254             concepts::model_of(),
255             concepts::model_of(),
256             concepts::model_of<
257             CommonReference, detail::as_cref_t, detail::as_cref_t>(),
258             concepts::model_of(),
259             concepts::model_of(),
260             concepts::model_of()
261             ));
262             };
263             }
264              
265             template
266             using Invocable = concepts::models;
267              
268             template
269             using RegularInvocable = concepts::models;
270              
271             template
272             using Predicate = concepts::models;
273              
274             template
275             using Relation = concepts::models;
276             /// @}
277              
278             template
279             struct logical_negate_
280             {
281             private:
282             CONCEPT_ASSERT(Same>() && MoveConstructible());
283             FD pred_;
284             public:
285             CONCEPT_REQUIRES(DefaultConstructible())
286             constexpr logical_negate_()
287             noexcept(std::is_nothrow_default_constructible::value)
288             {}
289             template
290             typename U = meta::if_c, logical_negate_>(), T>,
291             CONCEPT_REQUIRES_(Constructible())>
292 319           explicit constexpr logical_negate_(T && pred)
293 319           : pred_(static_cast(pred))
294 319           {}
295              
296             // HACKHACKHACK GCC 4.8 is extremely confused about && and const&& qualifiers.
297             // Luckily they are rare - we'll simply break them.
298             #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5 && __GNUC_MINOR__ < 9
299             template
300             CONCEPT_REQUIRES_(Predicate())>
301             RANGES_CXX14_CONSTEXPR auto operator()(Args &&...args)
302             RANGES_DECLTYPE_NOEXCEPT(
303             !invoke(std::declval(), static_cast(args)...))
304             {
305             return !invoke(pred_, static_cast(args)...);
306             }
307             /// \overload
308             template
309             CONCEPT_REQUIRES_(Predicate())>
310             constexpr auto operator()(Args &&...args) const
311             RANGES_DECLTYPE_NOEXCEPT(
312             !invoke(std::declval(), static_cast(args)...))
313             {
314             return !invoke(pred_, static_cast(args)...);
315             }
316             #else // ^^^ GCC <= 4.8 / GCC > 4.8 vvvv
317             template
318             CONCEPT_REQUIRES_(Predicate())>
319 3132           RANGES_CXX14_CONSTEXPR auto operator()(Args &&...args) &
320             RANGES_DECLTYPE_NOEXCEPT(
321             !invoke(std::declval(), static_cast(args)...))
322             {
323 3132           return !invoke(pred_, static_cast(args)...);
324             }
325             /// \overload
326             template
327             CONCEPT_REQUIRES_(Predicate())>
328             constexpr auto operator()(Args &&...args) const &
329             RANGES_DECLTYPE_NOEXCEPT(
330             !invoke(std::declval(), static_cast(args)...))
331             {
332             return !invoke(pred_, static_cast(args)...);
333             }
334             /// \overload
335             template
336             CONCEPT_REQUIRES_(Predicate())>
337             RANGES_CXX14_CONSTEXPR auto operator()(Args &&...args) &&
338             RANGES_DECLTYPE_NOEXCEPT(
339             !invoke(std::declval(), static_cast(args)...))
340             {
341             return !invoke(static_cast(pred_), static_cast(args)...);
342             }
343             /// \overload
344             template
345             CONCEPT_REQUIRES_(Predicate())>
346             RANGES_CXX14_CONSTEXPR auto operator()(Args &&...args) const &&
347             RANGES_DECLTYPE_NOEXCEPT(
348             !invoke(std::declval(), static_cast(args)...))
349             {
350             return !invoke(static_cast(pred_), static_cast(args)...);
351             }
352             #endif // GCC
353             };
354              
355             struct not_fn_fn
356             {
357             template,
358             CONCEPT_REQUIRES_(MoveConstructible() && Constructible())>
359 319           constexpr logical_negate_ operator()(Pred && pred) const
360             {
361 319           return logical_negate_{(Pred &&) pred};
362             }
363             };
364              
365             /// \ingroup group-utility
366             /// \sa `not_fn_fn`
367             RANGES_INLINE_VARIABLE(not_fn_fn, not_fn)
368              
369             /// \cond
370             inline namespace
371             {
372             RANGES_DEPRECATED("\"not_\" now uses the C++17 name \"not_fn\".")
373             constexpr const auto& not_ = not_fn;
374             }
375             /// \endcond
376              
377             template
378             struct composed
379             : private compressed_pair
380             {
381             private:
382             using composed::compressed_pair::first;
383             using composed::compressed_pair::second;
384             template
385             static auto do_(A &a, B &b, std::false_type, Ts &&...ts)
386             RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
387             (
388             invoke(b, invoke(a, (Ts &&) ts...))
389             )
390             template
391             static auto do_(A &a, B &b, std::true_type, Ts &&...ts)
392             RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
393             (
394             (invoke(a, (Ts &&) ts...),
395             invoke(b))
396             )
397             public:
398             composed() = default;
399             composed(Second second, First first)
400             : composed::compressed_pair{std::move(first), std::move(second)}
401             {}
402             template
403             typename FirstResultT = invoke_result_t>
404             auto operator()(Ts &&...ts)
405             RANGES_DECLTYPE_NOEXCEPT(composed::do_(
406             std::declval(),
407             std::declval(),
408             std::is_void{},
409             (Ts &&) ts...))
410             {
411             return composed::do_(
412             first(), second(),
413             std::is_void{},
414             (Ts &&) ts...);
415             }
416             template
417             typename FirstResultT = invoke_result_t>
418             auto operator()(Ts &&...ts) const
419             RANGES_DECLTYPE_NOEXCEPT(composed::do_(
420             std::declval(),
421             std::declval(),
422             std::is_void{},
423             (Ts &&) ts...))
424             {
425             return composed::do_(
426             first(), second(),
427             std::is_void{},
428             (Ts &&) ts...);
429             }
430             };
431              
432             struct compose_fn
433             {
434             template
435             composed operator()(Second second, First first) const
436             {
437             return {std::move(second), std::move(first)};
438             }
439             };
440              
441             /// \ingroup group-utility
442             /// \sa `compose_fn`
443             RANGES_INLINE_VARIABLE(compose_fn, compose)
444              
445             template<>
446             struct overloaded<>
447             {};
448              
449             template
450             struct overloaded
451             : private compressed_pair>
452             {
453             private:
454             using base_t = compressed_pair>;
455             using base_t::first;
456             using base_t::second;
457             public:
458             overloaded() = default;
459             constexpr overloaded(First first, Rest... rest)
460             : overloaded::compressed_pair{
461             detail::move(first),
462             overloaded{detail::move(rest)...}}
463             {}
464             template
465             auto operator()(Args&&...args)
466             RANGES_DECLTYPE_NOEXCEPT(
467             invoke(std::declval(),
468             static_cast(args)...))
469             {
470             return invoke(first(), static_cast(args)...);
471             }
472             template
473             auto operator()(Args&&...args) const
474             RANGES_DECLTYPE_NOEXCEPT(
475             invoke(std::declval(),
476             static_cast(args)...))
477             {
478             return invoke(first(), static_cast(args)...);
479             }
480             template
481             auto operator()(Args&&...args)
482             RANGES_DECLTYPE_NOEXCEPT(
483             std::declval &>()(
484             static_cast(args)...))
485             {
486             return second()(static_cast(args)...);
487             }
488             template
489             auto operator()(Args&&...args) const
490             RANGES_DECLTYPE_NOEXCEPT(
491             std::declval const &>()(
492             static_cast(args)...))
493             {
494             return second()(static_cast(args)...);
495             }
496             };
497              
498             struct overload_fn
499             {
500             template
501             constexpr Fn operator()(Fn fn) const
502             {
503             return fn;
504             }
505              
506             template
507             constexpr overloaded operator()(Fns... fns) const
508             {
509             return overloaded{detail::move(fns)...};
510             }
511             };
512              
513             /// \ingroup group-utility
514             /// \sa `overload_fn`
515             RANGES_INLINE_VARIABLE(overload_fn, overload)
516              
517             template
518             struct indirected
519             : private box>
520             {
521             private:
522             using box>::get;
523             public:
524             indirected() = default;
525 319           indirected(Fn fn)
526 319           : indirected::box(std::move(fn))
527 319           {}
528             // value_type (needs no impl)
529             template
530             [[noreturn]] auto operator()(copy_tag, Its...) const ->
531             invoke_result_t...>
532             {
533             RANGES_EXPECT(false);
534             }
535              
536             // Reference
537             template
538 154           auto operator()(Its ...its)
539             RANGES_DECLTYPE_NOEXCEPT(invoke(std::declval(), *its...))
540             {
541 154           return invoke(get(), *its...);
542             }
543             template
544             auto operator()(Its ...its) const
545             RANGES_DECLTYPE_NOEXCEPT(invoke(std::declval(), *its...))
546             {
547             return invoke(get(), *its...);
548             }
549              
550             // Rvalue reference
551             template
552             auto operator()(move_tag, Its ...its)
553             noexcept(noexcept(aux::move(invoke(std::declval(), *its...)))) ->
554             aux::move_t(), *its...))>
555             {
556             return aux::move(invoke(get(), *its...));
557             }
558             template
559             auto operator()(move_tag, Its ...its) const
560             noexcept(noexcept(aux::move(invoke(std::declval(), *its...)))) ->
561             aux::move_t(), *its...))>
562             {
563             return aux::move(invoke(get(), *its...));
564             }
565             };
566              
567             struct indirect_fn
568             {
569             template
570 319           constexpr indirected operator()(Fn fn) const
571             {
572 319           return indirected{detail::move(fn)};
573             }
574             };
575              
576             /// \ingroup group-utility
577             /// \sa `indirect_fn`
578             RANGES_INLINE_VARIABLE(indirect_fn, indirect)
579              
580             template
581             struct transformed
582             : private compressed_pair
583             {
584             private:
585             using transformed::compressed_pair::first;
586             using transformed::compressed_pair::second;
587              
588             public:
589             transformed() = default;
590             constexpr transformed(Fn1 fn1, Fn2 fn2)
591             : transformed::compressed_pair{detail::move(fn1), detail::move(fn2)}
592             {}
593             template
594             auto operator()(Args &&... args)
595             RANGES_DECLTYPE_NOEXCEPT(
596             invoke(std::declval(), invoke(std::declval(), static_cast(args))...))
597             {
598             return invoke(first(), invoke(second(), static_cast(args)...));
599             }
600             template
601             auto operator()(Args &&... args) const
602             RANGES_DECLTYPE_NOEXCEPT(
603             invoke(std::declval(), invoke(std::declval(), static_cast(args))...))
604             {
605             return invoke(first(), invoke(second(), static_cast(args)...));
606             }
607             };
608              
609             struct on_fn
610             {
611             template
612             constexpr transformed operator()(Fn1 fn1, Fn2 fn2) const
613             {
614             return transformed{detail::move(fn1), detail::move(fn2)};
615             }
616             };
617              
618             /// \ingroup group-utility
619             /// \sa `on_fn`
620             RANGES_INLINE_VARIABLE(on_fn, on)
621              
622             /// \cond
623             namespace detail
624             {
625             template
626 2552           struct RANGES_EMPTY_BASES pipeable_binder
627             : Bind
628             , pipeable>
629             {
630 638           pipeable_binder(Bind bind)
631 638           : Bind(std::move(bind))
632 638           {}
633             };
634              
635             template
636             struct composed_pipe
637             {
638             Pipe0 pipe0_;
639             Pipe1 pipe1_;
640             template
641             auto operator()(Arg && arg) const
642             RANGES_DECLTYPE_AUTO_RETURN
643             (
644             static_cast(arg) | pipe0_ | pipe1_
645             )
646             };
647             }
648             /// \endcond
649              
650             struct make_pipeable_fn
651             {
652             template
653 638           detail::pipeable_binder operator()(Fun fun) const
654             {
655 638           return {std::move(fun)};
656             }
657             };
658              
659             /// \ingroup group-utility
660             /// \sa `make_pipeable_fn`
661             RANGES_INLINE_VARIABLE(make_pipeable_fn, make_pipeable)
662              
663             template
664             typename U = meta::if_<
665             std::is_lvalue_reference,
666             std::reference_wrapper>>,
667             T &&>>
668             U bind_forward(meta::_t> &t) noexcept
669             {
670             return static_cast(t);
671             }
672              
673             template
674             T && bind_forward(meta::_t> &&t) noexcept
675             {
676             // This is to catch way sketchy stuff like: forward(42)
677             static_assert(!std::is_lvalue_reference::value, "You didn't just do that!");
678             return static_cast(t);
679             }
680              
681 1276           struct pipeable_base
682             {};
683              
684             template
685             struct is_pipeable
686             : std::is_base_of
687             {};
688              
689             template
690             struct is_pipeable
691             : is_pipeable
692             {};
693              
694             struct pipeable_access
695             {
696             template
697             struct impl : Pipeable
698             {
699             using Pipeable::pipe;
700             };
701              
702             template
703             struct impl : impl
704             {};
705             };
706              
707             template
708 2552           struct pipeable : pipeable_base
709             {
710             private:
711             friend pipeable_access;
712             // Default Pipe behavior just passes the argument to the pipe's function call
713             // operator
714             template
715             static auto pipe(Arg && arg, Pipe pipe)
716             RANGES_DECLTYPE_AUTO_RETURN
717             (
718             pipe(static_cast(arg))
719             )
720             };
721              
722             // Evaluate the pipe with an argument
723             template
724             CONCEPT_REQUIRES_(!is_pipeable() && is_pipeable())>
725 638           auto operator|(Arg && arg, Pipe pipe)
726 638           RANGES_DECLTYPE_AUTO_RETURN
727             (
728             pipeable_access::impl::pipe(static_cast(arg), pipe)
729             )
730              
731             // Compose two pipes
732             template
733             CONCEPT_REQUIRES_(is_pipeable() && is_pipeable())>
734             auto operator|(Pipe0 pipe0, Pipe1 pipe1)
735             RANGES_DECLTYPE_AUTO_RETURN
736             (
737             make_pipeable(detail::composed_pipe{pipe0, pipe1})
738             )
739              
740             template
741             struct bind_element
742             : meta::if_<
743             std::is_same, T>,
744             meta::id,
745             bind_element>>
746             {};
747              
748             template
749             struct bind_element>
750             {
751             using type = T &;
752             };
753              
754             template
755             struct bind_element>
756             {
757             using type = typename reference_wrapper::reference;
758             };
759              
760             template
761             using bind_element_t = meta::_t>;
762              
763             struct ref_fn : pipeable
764             {
765             template())>
766             reference_wrapper operator()(T &t) const
767             {
768             return {t};
769             }
770             /// \overload
771             template
772             reference_wrapper operator()(reference_wrapper t) const
773             {
774             return t;
775             }
776             /// \overload
777             template
778             reference_wrapper operator()(std::reference_wrapper t) const
779             {
780             return {t.get()};
781             }
782             };
783              
784             /// \ingroup group-utility
785             /// \sa `ref_fn`
786             RANGES_INLINE_VARIABLE(ref_fn, ref)
787              
788             template
789             using ref_t = decltype(ref(std::declval()));
790              
791             struct unwrap_reference_fn : pipeable
792             {
793             template())>
794             T &&operator()(T &&t) const noexcept
795             {
796             return static_cast(t);
797             }
798             /// \overload
799             template
800             typename reference_wrapper::reference
801             operator()(reference_wrapper t) const noexcept
802             {
803             return t.get();
804             }
805             /// \overload
806             template
807             T &operator()(std::reference_wrapper t) const noexcept
808             {
809             return t.get();
810             }
811             };
812              
813             /// \ingroup group-utility
814             /// \sa `unwrap_reference_fn`
815             RANGES_INLINE_VARIABLE(unwrap_reference_fn, unwrap_reference)
816              
817             template
818             using unwrap_reference_t = decltype(unwrap_reference(std::declval()));
819              
820             /// \cond
821             namespace detail
822             {
823             template
824             struct protect
825             {
826             private:
827             Bind bind_;
828             public:
829             protect() = default;
830             protect(Bind b)
831             : bind_(std::move(b))
832             {}
833             template
834             auto operator()(Ts &&...ts)
835             RANGES_DECLTYPE_AUTO_RETURN
836             (
837             bind_(static_cast(ts)...)
838             )
839             /// \overload
840             template
841             auto operator()(Ts &&...ts) const
842             RANGES_DECLTYPE_AUTO_RETURN
843             (
844             bind_(static_cast(ts)...)
845             )
846             };
847             }
848             /// \endcond
849              
850             struct protect_fn
851             {
852             template>())>
853             detail::protect> operator()(F && f) const
854             {
855             return {static_cast(f)};
856             }
857             /// \overload
858             template>())>
859 638           F operator()(F && f) const
860             {
861 638           return static_cast(f);
862             }
863             };
864              
865             /// Protect a callable so that it can be safely used in a bind expression without
866             /// accidentally becoming a "nested" bind.
867             /// \ingroup group-utility
868             /// \sa `protect_fn`
869             RANGES_INLINE_VARIABLE(protect_fn, protect)
870              
871             // Accepts initializer_lists as either the first or second parameter, or both,
872             // and forwards on to an implementation.
873             template
874             struct with_braced_init_args
875             : ImplFn
876             {
877             private:
878             constexpr ImplFn const & base() const
879             {
880             return *this;
881             }
882             public:
883             using ImplFn::operator();
884              
885             template
886             constexpr
887             auto operator()(std::initializer_list &&rng0, Args &&...args) const ->
888             decltype(std::declval()(std::move(rng0), std::declval()...))
889             {
890             return base()(std::move(rng0), static_cast(args)...);
891             }
892             /// \overload
893             template
894             constexpr
895             auto operator()(Rng0 && rng0, std::initializer_list &&rng1, Args &&...args) const ->
896             decltype(std::declval()(std::declval(), std::move(rng1), std::declval()...))
897             {
898             return base()(static_cast(rng0), std::move(rng1), static_cast(args)...);
899             }
900             /// \overload
901             template
902             constexpr
903             auto operator()(std::initializer_list rng0, std::initializer_list &&rng1, Args &&...args) const ->
904             decltype(std::declval()(std::move(rng0), std::move(rng1), std::declval()...))
905             {
906             return base()(std::move(rng0), std::move(rng1), static_cast(args)...);
907             }
908             };
909             /// @}
910             }
911             }
912              
913             RANGES_RE_ENABLE_WARNINGS
914              
915             #endif