File indexing completed on 2025-12-15 10:26:39
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
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
0031
0032
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
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
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
0083
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
0164
0165 template<typename Fn, typename... Args>
0166 using bind_back_fn = bind_back_fn_<decay_t<Fn>, decay_t<Args>...>;
0167 }
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
0185
0186 RANGES_INLINE_VARIABLE(bind_back_fn, bind_back)
0187
0188 }
0189
0190 #include <range/v3/detail/epilogue.hpp>
0191
0192 #endif