Header file range/v3/utility/functional.hpp

#include <meta/meta.hpp>

#include <range/v3/range_fwd.hpp>

#include <range/v3/utility/box.hpp>

#include <range/v3/utility/move.hpp>

#include <range/v3/utility/concepts.hpp>

#include <range/v3/utility/static_const.hpp>

#include <range/v3/utility/compressed_pair.hpp>

namespace ranges
{
    inline namespace v3
    {
        struct equal_to;
        
        struct not_equal_to
        {
            template <typename T, typename U, int _concept_requires_51 = 42, typename std::enable_if<(_concept_requires_51==43)||(EqualityComparable<T, U>()), int>::type=0>
            constexpr bool operator()(T&& t, U&& u) const;
            
            using is_transparent = void;
        };
        
        struct less
        {
            template <typename T, typename U, int _concept_requires_62 = 42, typename std::enable_if<(_concept_requires_62==43)||(WeaklyOrdered<T, U>()), int>::type=0>
            constexpr bool operator()(T&& t, U&& u) const;
            
            using is_transparent = void;
        };
        
        struct ordered_less
        {
            template <typename T, typename U, int _concept_requires_73 = 42, typename std::enable_if<(_concept_requires_73==43)||(TotallyOrdered<T, U>()), int>::type=0>
            constexpr bool operator()(T&& t, U&& u) const;
            
            using is_transparent = void;
        };
        
        struct ident
        {
            template <typename T>
            T&& operator()(T&& t) const noexcept;
            
            using is_transparent = void;
        };
        
        struct plus
        {
            template <typename T, typename U>
            decltype((T&&)t+(U&&)u) operator()(T&& t, U&& u) const;
            
            using is_transparent = void;
        };
        
        struct minus
        {
            template <typename T, typename U>
            decltype((T&&)t-(U&&)u) operator()(T&& t, U&& u) const;
            
            using is_transparent = void;
        };
        
        struct multiplies
        {
            template <typename T, typename U>
            decltype((T&&)t*(U&&)u) operator()(T&& t, U&& u) const;
            
            using is_transparent = void;
        };
        
        struct bitwise_or
        {
            template <typename T, typename U>
            decltype((T&&)t|(U&&)u) operator()(T&& t, U&& u) const;
            
            using is_transparent = void;
        };
        
        template <typename T>
        struct convert_to
        {
            template <typename U, int _concept_requires_139 = 42, typename std::enable_if<(_concept_requires_139==43)||(std::is_constructible<T, U>::value), int>::type=0>
            constexpr decltype(static_cast<T>((U&&)u)) operator()(U&& u) const noexcept(noexcept(decltype(static_cast<T>((U&&)u))(static_cast<T>((U&&)u))));
        };
        
        template <typename T>
        struct coerce
        {
            T& operator()(T& t) const;
            
            T const& operator()(T const& t) const;
            
            T operator()(T&& t) const;
            
            T operator()(T const&&) const = delete;
        };
        
        template <typename T>
        struct coerce<T const>
        : coerce<T>
        {};
        
        template <typename T>
        struct coerce<T&>
        : coerce<T>
        {};
        
        template <typename T>
        struct coerce<T&&>
        : coerce<T>
        {};
        
        struct as_function_fn
        {
            template <typename R, typename ... Args>
            constexpr ptr_fn_<R, Args...> operator()(R(*p)(Args...)) const;
            
            template <typename R, typename T>
            decltype(_mem_fn(p)) operator()(R T::* p) const;
            
            template <typename T, typename U = detail::decay_t<T>>
            constexpr meta::if_c<!std::is_pointer<U>::value&&!std::is_member_pointer<U>::value, T> operator()(T&& t) const;
        };
        
        inline namespace 
        {
            constexpr auto& as_function = static_const<as_function_fn>::value;
        }
        
        template <typename T>
        using function_type = decltype(as_function(std::declval<T>()));
        
        namespace concepts
        {
            struct Callable
            {
                template <typename Fun, typename ... Args>
                using result_t = Function::result_t<function_type<Fun>, Args...>;
                
                template <typename Fun, typename ... Args>
                decltype(concepts::valid_expr(concepts::model_of<Function, function_type<Fun>, Args...>())) requires_(Fun&&, Args&&...);
            };
            
            struct RegularCallable
            : refines<struct ranges::v3::concepts::Callable>
            {};
            
            struct CallablePredicate
            : refines<struct ranges::v3::concepts::RegularCallable>
            {
                template <typename Fun, typename ... Args>
                decltype(concepts::valid_expr(concepts::model_of<Predicate, function_type<Fun>, Args...>())) requires_(Fun&&, Args&&...);
            };
            
            struct CallableRelation
            : refines<struct ranges::v3::concepts::CallablePredicate>
            {
                template <typename Fun, typename T, typename U>
                decltype(concepts::valid_expr(concepts::model_of<Relation, function_type<Fun>, T, U>())) requires_(Fun&&, T&&, U&&);
            };
        }
        
        template <typename Fun, typename ... Args>
        using Callable = concepts::models<concepts::Callable, Fun, Args...>;
        
        template <typename Fun, typename ... Args>
        using RegularCallable = concepts::models<concepts::RegularCallable, Fun, Args...>;
        
        template <typename Fun, typename ... Args>
        using CallablePredicate = concepts::models<concepts::CallablePredicate, Fun, Args...>;
        
        template <typename Fun, typename T, typename U = T>
        using CallableRelation = concepts::models<concepts::CallableRelation, Fun, T, U>;
        
        template <typename Pred>
        struct logical_negate
        {
            logical_negate() = default;
            
            explicit constexpr logical_negate(Pred pred);
            
            template <typename ... Args, int _concept_requires_330 = 42, typename std::enable_if<(_concept_requires_330==43)||(Predicate<fn_t&, Args>()), int>::type ... = 0>
            bool operator()(Args&&... args);
            
            template <typename ... Args, int _concept_requires_337 = 42, typename std::enable_if<(_concept_requires_337==43)||(Predicate<fn_t const&, Args>()), int>::type ... = 0>
            constexpr bool operator()(Args&&... args) const;
        };
        
        struct not_fn
        {
            template <typename Pred>
            constexpr logical_negate<Pred> operator()(Pred pred) const;
        };
        
        inline namespace 
        {
            constexpr auto& not_ = static_const<not_fn>::value;
        }
        
        template <typename Second, typename First>
        struct composed
        {
            composed() = default;
            
            composed(Second second, First first);
            
            template <typename ... Ts, typename FirstResultT = concepts::Function::result_t<function_type<First>&, Ts&&...>>
            decltype(composed::do_(std::declval<function_type<First>&>(), std::declval<function_type<Second>&>(), std::is_void<FirstResultT>{}, (Ts&&)ts...)) operator()(Ts&&... ts) noexcept(noexcept(decltype(composed::do_(std::declval<function_type<First>&>(), std::declval<function_type<Second>&>(), std::is_void<FirstResultT>{}, (Ts&&)ts...))(composed::do_(std::declval<function_type<First>&>(), std::declval<function_type<Second>&>(), std::is_void<FirstResultT>{}, (Ts&&)ts...))));
            
            template <typename ... Ts, typename FirstResultT = concepts::Function::result_t<function_type<First>const&, Ts&&...>>
            decltype(composed::do_(std::declval<function_type<First>const&>(), std::declval<function_type<Second>const&>(), std::is_void<FirstResultT>{}, (Ts&&)ts...)) operator()(Ts&&... ts) const noexcept(noexcept(decltype(composed::do_(std::declval<function_type<First>const&>(), std::declval<function_type<Second>const&>(), std::is_void<FirstResultT>{}, (Ts&&)ts...))(composed::do_(std::declval<function_type<First>const&>(), std::declval<function_type<Second>const&>(), std::is_void<FirstResultT>{}, (Ts&&)ts...))));
        };
        
        struct compose_fn
        {
            template <typename Second, typename First>
            composed<Second, First> operator()(Second second, First first) const;
        };
        
        inline namespace 
        {
            constexpr auto& compose = static_const<compose_fn>::value;
        }
        
        struct overload_fn
        {
            template <typename Fn>
            constexpr function_type<Fn> operator()(Fn fn) const;
            
            template <typename ... Fns>
            constexpr overloaded<Fns...> operator()(Fns... fns) const;
        };
        
        inline namespace 
        {
            constexpr auto& overload = static_const<overload_fn>::value;
        }
        
        template <typename Fn>
        struct indirected
        {
            indirected() = default;
            
            indirected(Fn fn);
            
            template <typename ... Its>
            decltype(std::declval<BaseFn&>()(*std::declval<Its>()...)) operator()(copy_tag, Its...) const;
            
            template <typename ... Its>
            decltype(std::declval<BaseFn&>()(*its...)) operator()(Its... its) noexcept(noexcept(decltype(std::declval<BaseFn&>()(*its...))(std::declval<BaseFn&>()(*its...))));
            
            template <typename ... Its>
            decltype(std::declval<BaseFn const&>()(*its...)) operator()(Its... its) const noexcept(noexcept(decltype(std::declval<BaseFn const&>()(*its...))(std::declval<BaseFn const&>()(*its...))));
            
            template <typename ... Its>
            aux::move_t<decltype(std::declval<BaseFn&>()(*its...))> operator()(move_tag, Its... its) noexcept(noexcept(aux::move(std::declval<BaseFn&>()(*its...))));
            
            template <typename ... Its>
            aux::move_t<decltype(std::declval<BaseFn const&>()(*its...))> operator()(move_tag, Its... its) const noexcept(noexcept(aux::move(std::declval<BaseFn const&>()(*its...))));
        };
        
        struct indirect_fn
        {
            template <typename Fn>
            constexpr indirected<Fn> operator()(Fn fn) const;
        };
        
        inline namespace 
        {
            constexpr auto& indirect = static_const<indirect_fn>::value;
        }
        
        template <typename Fn1, typename Fn2>
        struct transformed
        {
            transformed() = default;
            
            constexpr transformed(Fn1 fn1, Fn2 fn2);
            
            template <typename ... Args>
            decltype(std::declval<BaseFn1&>()(std::declval<BaseFn2&>()(std::forward<Args>(args))...)) operator()(Args&&... args) noexcept(noexcept(decltype(std::declval<BaseFn1&>()(std::declval<BaseFn2&>()(std::forward<Args>(args))...))(std::declval<BaseFn1&>()(std::declval<BaseFn2&>()(std::forward<Args>(args))...))));
            
            template <typename ... Args>
            decltype(std::declval<BaseFn1 const&>()(std::declval<BaseFn2 const&>()(std::forward<Args>(args))...)) operator()(Args&&... args) const noexcept(noexcept(decltype(std::declval<BaseFn1 const&>()(std::declval<BaseFn2 const&>()(std::forward<Args>(args))...))(std::declval<BaseFn1 const&>()(std::declval<BaseFn2 const&>()(std::forward<Args>(args))...))));
        };
        
        struct on_fn
        {
            template <typename Fn1, typename Fn2>
            constexpr transformed<Fn1, Fn2> operator()(Fn1 fn1, Fn2 fn2) const;
        };
        
        inline namespace 
        {
            constexpr auto& on = static_const<on_fn>::value;
        }
        
        namespace detail
        {
            template <typename Bind>
            struct pipeable_binder
            : Bind, pipeable<pipeable_binder<Bind> >
            {
                pipeable_binder(Bind bind);
            };
            
            template <typename Pipe0, typename Pipe1>
            struct composed_pipe
            {
                Pipe0 pipe0_;
                
                Pipe1 pipe1_;
                
                template <typename Arg>
                decltype(std::forward<Arg>(arg)|pipe0_|pipe1_) operator()(Arg&& arg) const;
            };
        }
        
        struct make_pipeable_fn
        {
            template <typename Fun>
            detail::pipeable_binder<Fun> operator()(Fun fun) const;
        };
        
        inline namespace 
        {
            constexpr auto& make_pipeable = static_const<make_pipeable_fn>::value;
        }
        
        template <typename T, typename U = meta::if_<std::is_lvalue_reference<T>, std::reference_wrapper<meta::_t<std::remove_reference<T>>>, T&&>>
        U bind_forward(meta::_t<std::remove_reference<T>>& t) noexcept;
        
        template <typename T>
        T&& bind_forward(meta::_t<std::remove_reference<T>>&& t) noexcept;
        
        struct pipeable_base{};
        
        template <typename T>
        struct is_pipeable
        : std::is_base_of<pipeable_base, T>
        {};
        
        template <typename T>
        struct is_pipeable<T&>
        : is_pipeable<T>
        {};
        
        struct pipeable_access
        {
            template <typename Pipeable>
            struct impl
            : Pipeable
            {
                using Pipeable::pipe;
            };
            
            template <typename Pipeable>
            struct impl<Pipeable&>
            : impl<Pipeable>
            {};
        };
        
        template <typename Derived>
        struct pipeable
        : ranges::v3::pipeable_base
        {
        };
        
        template <typename Arg, typename Pipe, int _concept_requires_712 = 42, typename std::enable_if<(_concept_requires_712==43)||(!is_pipeable<Arg>()&&is_pipeable<Pipe>()), int>::type=0>
        decltype(pipeable_access::impl<Pipe>::pipe(std::forward<Arg>(arg), pipe)) operator|(Arg&& arg, Pipe pipe);
        
        template <typename Pipe0, typename Pipe1, int _concept_requires_721 = 42, typename std::enable_if<(_concept_requires_721==43)||(is_pipeable<Pipe0>()&&is_pipeable<Pipe1>()), int>::type=0>
        decltype(make_pipeable(detail::composed_pipe<Pipe0, Pipe1>{pipe0, pipe1})) operator|(Pipe0 pipe0, Pipe1 pipe1);
        
        template <typename T, bool RValue>
        struct reference_wrapper
        {
            using type = T;
            
            using reference = meta::if_c<RValue, T&&, T&>;
            
            constexpr reference_wrapper() = default;
            
            constexpr reference_wrapper(reference t) noexcept;
            
            constexpr reference get() const noexcept;
            
            constexpr operator reference() const noexcept;
            
            template <int _concept_requires_748 = 42, typename std::enable_if<(_concept_requires_748==43)||(!RValue), int>::type=0>
            operator std::reference_wrapper<T>() const noexcept;
            
            template <typename ... Args>
            constexpr decltype(std::declval<reference>()(std::declval<Args>()...)) operator()(Args&&... args) const noexcept(noexcept(decltype(std::declval<reference>()(std::declval<Args>()...))(std::declval<reference>()(std::declval<Args>()...))));
        };
        
        template <typename T>
        struct is_reference_wrapper
        : meta::if_<std::is_same<uncvref_t<T>, T>, std::false_type, is_reference_wrapper<uncvref_t<T> > >
        {};
        
        template <typename T, bool RValue>
        struct is_reference_wrapper<reference_wrapper<T, RValue>>
        : std::true_type
        {};
        
        template <typename T>
        struct is_reference_wrapper<std::reference_wrapper<T>>
        : std::true_type
        {};
        
        template <typename T>
        using is_reference_wrapper_t = meta::_t<is_reference_wrapper<T>>;
        
        template <typename T>
        struct reference_of{};
        
        template <typename T, bool RValue>
        struct reference_of<reference_wrapper<T, RValue>>
        {
            using type = meta::if_c<RValue, T&&, T&>;
        };
        
        template <typename T>
        struct reference_of<std::reference_wrapper<T>>
        {
            using type = T&;
        };
        
        template <typename T>
        struct reference_of<T&>
        : meta::if_<is_reference_wrapper<T>, reference_of<T>, meta::id<T &> >
        {};
        
        template <typename T>
        struct reference_of<T&&>
        : meta::if_<is_reference_wrapper<T>, reference_of<T>, meta::id<T &&> >
        {};
        
        template <typename T>
        struct reference_of<T const>
        : reference_of<T>
        {};
        
        template <typename T>
        using reference_of_t = meta::_t<reference_of<T>>;
        
        template <typename T>
        struct bind_element
        : meta::if_<std::is_same<detail::decay_t<T>, T>, meta::id<T>, bind_element<detail::decay_t<T> > >
        {};
        
        template <typename T>
        struct bind_element<std::reference_wrapper<T>>
        {
            using type = T&;
        };
        
        template <typename T, bool RValue>
        struct bind_element<reference_wrapper<T, RValue>>
        {
            using type = meta::if_c<RValue, T&&, T&>;
        };
        
        struct ref_fn
        : pipeable<struct ranges::v3::ref_fn>
        {
            template <typename T, int _concept_requires_842 = 42, typename std::enable_if<(_concept_requires_842==43)||(!is_reference_wrapper_t<T>()), int>::type=0>
            reference_wrapper<T> operator()(T& t) const;
            
            template <typename T, bool RValue>
            reference_wrapper<T, RValue> operator()(reference_wrapper<T, RValue> t) const;
            
            template <typename T>
            reference_wrapper<T> operator()(std::reference_wrapper<T> t) const;
        };
        
        inline namespace 
        {
            constexpr auto& ref = static_const<ref_fn>::value;
        }
        
        template <typename T>
        using ref_t = decltype(ref(std::declval<T>()));
        
        struct rref_fn
        : pipeable<struct ranges::v3::rref_fn>
        {
            template <typename T, int _concept_requires_871 = 42, typename std::enable_if<(_concept_requires_871==43)||(!is_reference_wrapper_t<T>()&&!std::is_lvalue_reference<T>::value), int>::type=0>
            reference_wrapper<T, true> operator()(T&& t) const;
            
            template <typename T>
            reference_wrapper<T, true> operator()(reference_wrapper<T, true> t) const;
        };
        
        inline namespace 
        {
            constexpr auto& rref = static_const<rref_fn>::value;
        }
        
        template <typename T>
        using rref_t = decltype(rref(std::declval<T>()));
        
        struct unwrap_reference_fn
        : pipeable<struct ranges::v3::unwrap_reference_fn>
        {
            template <typename T, int _concept_requires_894 = 42, typename std::enable_if<(_concept_requires_894==43)||(!is_reference_wrapper<T>()), int>::type=0>
            T&& operator()(T&& t) const noexcept;
            
            template <typename T, bool RValue>
            meta::if_c<RValue, T&&, T&> operator()(reference_wrapper<T, RValue> t) const noexcept;
            
            template <typename T>
            T& operator()(std::reference_wrapper<T> t) const noexcept;
        };
        
        inline namespace 
        {
            constexpr auto& unwrap_reference = static_const<unwrap_reference_fn>::value;
        }
        
        template <typename T>
        using unwrap_reference_t = decltype(unwrap_reference(std::declval<T>()));
        
        namespace detail
        {
            template <typename Bind>
            struct protect
            {
                protect() = default;
                
                protect(Bind b);
                
                template <typename ... Ts>
                decltype(bind_(std::forward<Ts>(ts)...)) operator()(Ts&&... ts);
                
                template <typename ... Ts>
                decltype(bind_(std::forward<Ts>(ts)...)) operator()(Ts&&... ts) const;
            };
        }
        
        struct protect_fn
        {
            template <typename F, int _concept_requires_952 = 42, typename std::enable_if<(_concept_requires_952==43)||(std::is_bind_expression<uncvref_t<F>>()), int>::type=0>
            detail::protect<uncvref_t<F>> operator()(F&& f) const;
            
            template <typename F, int _concept_requires_958 = 42, typename std::enable_if<(_concept_requires_958==43)||(!std::is_bind_expression<uncvref_t<F>>()), int>::type=0>
            F operator()(F&& f) const;
        };
        
        inline namespace 
        {
            constexpr auto& protect = static_const<protect_fn>::value;
        }
        
        template <typename ImplFn>
        struct with_braced_init_args
        : ImplFn
        {
            using ImplFn::operator();
            
            template <typename V0, typename ... Args>
            decltype(std::declval<ImplFn const&>()(std::move(rng0), std::declval<Args>()...)) operator()(std::initializer_list<V0>&& rng0, Args&&... args) const;
            
            template <typename Rng0, typename V1, typename ... Args>
            decltype(std::declval<ImplFn const&>()(std::declval<Rng0>(), std::move(rng1), std::declval<Args>()...)) operator()(Rng0&& rng0, std::initializer_list<V1>&& rng1, Args&&... args) const;
            
            template <typename V0, typename V1, typename ... Args>
            decltype(std::declval<ImplFn const&>()(std::move(rng0), std::move(rng1), std::declval<Args>()...)) operator()(std::initializer_list<V0> rng0, std::initializer_list<V1>&& rng1, Args&&... args) const;
        };
    }
}

Class ranges::v3::equal_to

struct equal_to
{
    template <typename T, typename U, int _concept_requires_40 = 42, typename std::enable_if<(_concept_requires_40==43)||(EqualityComparable<T, U>()), int>::type=0>
    constexpr bool operator()(T&& t, U&& u) const;
    
    using is_transparent = void;
};

@{


Variable ranges::v3::as_function

constexpr auto& as_function = static_const<as_function_fn>::value;

make_invokable_fn


Variable ranges::v3::not_

constexpr auto& not_ = static_const<not_fn>::value;

not_fn


Variable ranges::v3::compose

constexpr auto& compose = static_const<compose_fn>::value;

compose_fn


Variable ranges::v3::overload

constexpr auto& overload = static_const<overload_fn>::value;

overload_fn


Variable ranges::v3::indirect

constexpr auto& indirect = static_const<indirect_fn>::value;

indirect_fn


Variable ranges::v3::on

constexpr auto& on = static_const<on_fn>::value;

on_fn


Variable ranges::v3::make_pipeable

constexpr auto& make_pipeable = static_const<make_pipeable_fn>::value;

make_pipeable_fn


Variable ranges::v3::ref

constexpr auto& ref = static_const<ref_fn>::value;

ref_fn


Variable ranges::v3::rref

constexpr auto& rref = static_const<rref_fn>::value;

rref_fn


Variable ranges::v3::unwrap_reference

constexpr auto& unwrap_reference = static_const<unwrap_reference_fn>::value;

unwrap_reference_fn


Variable ranges::v3::protect

constexpr auto& protect = static_const<protect_fn>::value;

Protect a callable so that it can be safely used in a bind expression without accidentally becoming a "nested" bind. protect_fn