Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-15 10:26:39

0001 /// \file
0002 // Range v3 library
0003 //
0004 //  Copyright Andrey Diduh 2019
0005 //
0006 //  Use, modification and distribution is subject to the
0007 //  Boost Software License, Version 1.0. (See accompanying
0008 //  file LICENSE_1_0.txt or copy at
0009 //  http://www.boost.org/LICENSE_1_0.txt)
0010 //
0011 // Project home: https://github.com/ericniebler/range-v3
0012 //
0013 
0014 #ifndef RANGES_V3_DETAIL_BIND_BACK_HPP
0015 #define RANGES_V3_DETAIL_BIND_BACK_HPP
0016 
0017 #include <tuple>
0018 
0019 #include <meta/meta.hpp>
0020 
0021 #include <range/v3/range_fwd.hpp>
0022 
0023 #include <range/v3/functional/invoke.hpp>
0024 #include <range/v3/utility/tuple_algorithm.hpp>
0025 
0026 #include <range/v3/detail/prologue.hpp>
0027 
0028 namespace ranges
0029 {
0030     // bind_back like std::bind_front has no special treatment for nested
0031     // bind-expressions or reference_wrappers; there is no need to wrap
0032     // Callables with ranges::protect.
0033     namespace detail
0034     {
0035         template<typename Fn, typename... Args>
0036         struct bind_back_fn_
0037         {
0038             using tuple_t = std::tuple<Fn, Args...>;
0039             tuple_t fn_args_;
0040 
0041             template<typename... CallArgs>
0042             constexpr invoke_result_t<Fn, CallArgs..., Args...> //
0043             operator()(CallArgs &&... cargs) &&
0044                 noexcept(is_nothrow_invocable_v<Fn, CallArgs..., Args...>)
0045             {
0046                 return tuple_apply(
0047                     [&](auto && fn, auto &&... args) -> decltype(auto) {
0048                         return invoke((decltype(fn))fn,
0049                                       (CallArgs &&) cargs...,
0050                                       (decltype(args))args...);
0051                     },
0052                     (std::tuple<Fn, Args...> &&) fn_args_);
0053             }
0054 
0055             /// \overload
0056             template<typename... CallArgs>
0057             constexpr invoke_result_t<Fn &, CallArgs..., Args &...>
0058             operator()(CallArgs &&... cargs) &
0059                 noexcept(is_nothrow_invocable_v<Fn &, CallArgs..., Args &...>)
0060             {
0061                 return tuple_apply(
0062                     [&](auto & fn, auto &... args) -> decltype(auto) {
0063                         return invoke(fn, (CallArgs &&) cargs..., args...);
0064                     },
0065                     fn_args_);
0066             }
0067 
0068             /// \overload
0069             template<typename... CallArgs>
0070             constexpr invoke_result_t<Fn const &, CallArgs..., Args const &...>
0071             operator()(CallArgs &&... cargs) const & //
0072                 noexcept(is_nothrow_invocable_v<Fn const &, CallArgs..., Args const &...>)
0073             {
0074                 return tuple_apply(
0075                     [&](auto & fn, auto &... args) -> decltype(auto) {
0076                         return invoke(fn, (CallArgs &&) cargs..., args...);
0077                     },
0078                     fn_args_);
0079             }
0080         };
0081 
0082         /// \cond
0083         // Unroll a few instantiations to avoid a heavy-weight tuple instantiation
0084         template<typename Fn, typename Arg>
0085         struct bind_back_fn_<Fn, Arg>
0086         {
0087             struct tuple_t
0088             {
0089                 Fn fn_;
0090                 Arg arg_;
0091             };
0092             tuple_t fn_args_;
0093 
0094             template<typename... CallArgs>
0095             constexpr invoke_result_t<Fn, CallArgs..., Arg> //
0096             operator()(CallArgs &&... cargs) && //
0097                 noexcept(is_nothrow_invocable_v<Fn, CallArgs..., Arg>)
0098             {
0099                 return invoke(
0100                     (Fn &&) fn_args_.fn_, (CallArgs &&) cargs..., (Arg &&) fn_args_.arg_);
0101             }
0102 
0103             template<typename... CallArgs>
0104             constexpr invoke_result_t<Fn &, CallArgs..., Arg &> //
0105             operator()(CallArgs &&... cargs) & //
0106                 noexcept(is_nothrow_invocable_v<Fn &, CallArgs..., Arg &>)
0107             {
0108                 return invoke(fn_args_.fn_, (CallArgs &&) cargs..., fn_args_.arg_);
0109             }
0110 
0111             template<typename... CallArgs>
0112             constexpr invoke_result_t<Fn const &, CallArgs..., Arg const &> //
0113             operator()(CallArgs &&... cargs) const & //
0114                 noexcept(is_nothrow_invocable_v<Fn const &, CallArgs..., Arg const &>)
0115             {
0116                 return invoke(fn_args_.fn_, (CallArgs &&) cargs..., fn_args_.arg_);
0117             }
0118         };
0119 
0120         template<typename Fn, typename Arg0, typename Arg1>
0121         struct bind_back_fn_<Fn, Arg0, Arg1>
0122         {
0123             struct tuple_t
0124             {
0125                 Fn fn_;
0126                 Arg0 arg0_;
0127                 Arg1 arg1_;
0128             };
0129             tuple_t fn_args_;
0130 
0131             template<typename... CallArgs>
0132             constexpr invoke_result_t<Fn, CallArgs..., Arg0, Arg1> //
0133             operator()(CallArgs &&... cargs) && //
0134                 noexcept(is_nothrow_invocable_v<Fn, CallArgs..., Arg0, Arg1>)
0135             {
0136                 return invoke((Fn &&) fn_args_.fn_,
0137                               (CallArgs &&) cargs...,
0138                               (Arg0 &&) fn_args_.arg0_,
0139                               (Arg1 &&) fn_args_.arg1_);
0140             }
0141 
0142             template<typename... CallArgs>
0143             constexpr invoke_result_t<Fn &, CallArgs..., Arg0 &, Arg1 &> //
0144             operator()(CallArgs &&... cargs) & //
0145                 noexcept(is_nothrow_invocable_v<Fn &, CallArgs..., Arg0 &, Arg1 &>)
0146             {
0147                 return invoke(
0148                     fn_args_.fn_, (CallArgs &&) cargs..., fn_args_.arg0_, fn_args_.arg1_);
0149             }
0150 
0151             template<typename... CallArgs>
0152             constexpr invoke_result_t<Fn const &, CallArgs..., Arg0 const &, Arg1 const &>
0153             operator()(CallArgs &&... cargs) const & 
0154                 noexcept(is_nothrow_invocable_v<Fn const &,
0155                                                 CallArgs...,
0156                                                 Arg0 const &,
0157                                                 Arg1 const &>)
0158             {
0159                 return invoke(
0160                     fn_args_.fn_, (CallArgs &&) cargs..., fn_args_.arg0_, fn_args_.arg1_);
0161             }
0162         };
0163         /// \endcond
0164 
0165         template<typename Fn, typename... Args>
0166         using bind_back_fn = bind_back_fn_<decay_t<Fn>, decay_t<Args>...>;
0167     } // namespace detail
0168 
0169     struct bind_back_fn
0170     {
0171         template<typename Fn, typename Arg1, typename... Args>
0172         constexpr detail::bind_back_fn<Fn, Arg1, Args...> //
0173         operator()(Fn && fn, Arg1 && arg1, Args &&... args) const
0174         {
0175 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5
0176             using T = typename detail::bind_back_fn<Fn, Arg1, Args...>::tuple_t;
0177             return {T{(Fn &&) fn, (Arg1 &&) arg1, (Args &&) args...}};
0178 #else
0179             return {{(Fn &&) fn, (Arg1 &&) arg1, (Args &&) args...}};
0180 #endif
0181         }
0182     };
0183 
0184     /// \ingroup group-utility
0185     /// \sa `bind_back_fn`
0186     RANGES_INLINE_VARIABLE(bind_back_fn, bind_back)
0187 
0188 } // namespace ranges
0189 
0190 #include <range/v3/detail/epilogue.hpp>
0191 
0192 #endif // RANGES_V3_DETAIL_BIND_BACK_HPP