Horizon
Loading...
Searching...
No Matches
bind_back.hpp
Go to the documentation of this file.
1
2// Range v3 library
3//
4// Copyright Andrey Diduh 2019
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_DETAIL_BIND_BACK_HPP
15#define RANGES_V3_DETAIL_BIND_BACK_HPP
16
17#include <tuple>
18
19#include <meta/meta.hpp>
20
22
25
26#include <range/v3/detail/prologue.hpp>
27
28namespace ranges
29{
30 // bind_back like std::bind_front has no special treatment for nested
31 // bind-expressions or reference_wrappers; there is no need to wrap
32 // Callables with ranges::protect.
33 namespace detail
34 {
35 template<typename Fn, typename... Args>
37 {
38 using tuple_t = std::tuple<Fn, Args...>;
39 tuple_t fn_args_;
40
41 template<typename... CallArgs>
42 constexpr invoke_result_t<Fn, CallArgs..., Args...> //
43 operator()(CallArgs &&... cargs) &&
44 noexcept(is_nothrow_invocable_v<Fn, CallArgs..., Args...>)
45 {
46 return tuple_apply(
47 [&](auto && fn, auto &&... args) -> decltype(auto) {
48 return invoke((decltype(fn))fn,
49 (CallArgs &&) cargs...,
50 (decltype(args))args...);
51 },
52 (std::tuple<Fn, Args...> &&) fn_args_);
53 }
54
56 template<typename... CallArgs>
57 constexpr invoke_result_t<Fn &, CallArgs..., Args &...>
58 operator()(CallArgs &&... cargs) &
59 noexcept(is_nothrow_invocable_v<Fn &, CallArgs..., Args &...>)
60 {
61 return tuple_apply(
62 [&](auto & fn, auto &... args) -> decltype(auto) {
63 return invoke(fn, (CallArgs &&) cargs..., args...);
64 },
65 fn_args_);
66 }
67
69 template<typename... CallArgs>
70 constexpr invoke_result_t<Fn const &, CallArgs..., Args const &...>
71 operator()(CallArgs &&... cargs) const & //
72 noexcept(is_nothrow_invocable_v<Fn const &, CallArgs..., Args const &...>)
73 {
74 return tuple_apply(
75 [&](auto & fn, auto &... args) -> decltype(auto) {
76 return invoke(fn, (CallArgs &&) cargs..., args...);
77 },
78 fn_args_);
79 }
80 };
81
83 // Unroll a few instantiations to avoid a heavy-weight tuple instantiation
84 template<typename Fn, typename Arg>
85 struct bind_back_fn_<Fn, Arg>
86 {
87 struct tuple_t
88 {
89 Fn fn_;
90 Arg arg_;
91 };
92 tuple_t fn_args_;
93
94 template<typename... CallArgs>
95 constexpr invoke_result_t<Fn, CallArgs..., Arg> //
96 operator()(CallArgs &&... cargs) && //
97 noexcept(is_nothrow_invocable_v<Fn, CallArgs..., Arg>)
98 {
99 return invoke(
100 (Fn &&) fn_args_.fn_, (CallArgs &&) cargs..., (Arg &&) fn_args_.arg_);
101 }
102
103 template<typename... CallArgs>
104 constexpr invoke_result_t<Fn &, CallArgs..., Arg &> //
105 operator()(CallArgs &&... cargs) & //
106 noexcept(is_nothrow_invocable_v<Fn &, CallArgs..., Arg &>)
107 {
108 return invoke(fn_args_.fn_, (CallArgs &&) cargs..., fn_args_.arg_);
109 }
110
111 template<typename... CallArgs>
112 constexpr invoke_result_t<Fn const &, CallArgs..., Arg const &> //
113 operator()(CallArgs &&... cargs) const & //
114 noexcept(is_nothrow_invocable_v<Fn const &, CallArgs..., Arg const &>)
115 {
116 return invoke(fn_args_.fn_, (CallArgs &&) cargs..., fn_args_.arg_);
117 }
118 };
119
120 template<typename Fn, typename Arg0, typename Arg1>
121 struct bind_back_fn_<Fn, Arg0, Arg1>
122 {
123 struct tuple_t
124 {
125 Fn fn_;
126 Arg0 arg0_;
127 Arg1 arg1_;
128 };
129 tuple_t fn_args_;
130
131 template<typename... CallArgs>
132 constexpr invoke_result_t<Fn, CallArgs..., Arg0, Arg1> //
133 operator()(CallArgs &&... cargs) && //
134 noexcept(is_nothrow_invocable_v<Fn, CallArgs..., Arg0, Arg1>)
135 {
136 return invoke((Fn &&) fn_args_.fn_,
137 (CallArgs &&) cargs...,
138 (Arg0 &&) fn_args_.arg0_,
139 (Arg1 &&) fn_args_.arg1_);
140 }
141
142 template<typename... CallArgs>
143 constexpr invoke_result_t<Fn &, CallArgs..., Arg0 &, Arg1 &> //
144 operator()(CallArgs &&... cargs) & //
145 noexcept(is_nothrow_invocable_v<Fn &, CallArgs..., Arg0 &, Arg1 &>)
146 {
147 return invoke(
148 fn_args_.fn_, (CallArgs &&) cargs..., fn_args_.arg0_, fn_args_.arg1_);
149 }
150
151 template<typename... CallArgs>
152 constexpr invoke_result_t<Fn const &, CallArgs..., Arg0 const &, Arg1 const &>
153 operator()(CallArgs &&... cargs) const &
154 noexcept(is_nothrow_invocable_v<Fn const &,
155 CallArgs...,
156 Arg0 const &,
157 Arg1 const &>)
158 {
159 return invoke(
160 fn_args_.fn_, (CallArgs &&) cargs..., fn_args_.arg0_, fn_args_.arg1_);
161 }
162 };
164
165 template<typename Fn, typename... Args>
166 using bind_back_fn = bind_back_fn_<decay_t<Fn>, decay_t<Args>...>;
167 } // namespace detail
168
170 {
171 template<typename Fn, typename Arg1, typename... Args>
172 constexpr detail::bind_back_fn<Fn, Arg1, Args...> //
173 operator()(Fn && fn, Arg1 && arg1, Args &&... args) const
174 {
175#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5
176 using T = typename detail::bind_back_fn<Fn, Arg1, Args...>::tuple_t;
177 return {T{(Fn &&) fn, (Arg1 &&) arg1, (Args &&) args...}};
178#else
179 return {{(Fn &&) fn, (Arg1 &&) arg1, (Args &&) args...}};
180#endif
181 }
182 };
183
186 RANGES_INLINE_VARIABLE(bind_back_fn, bind_back)
187
188} // namespace ranges
189
190#include <range/v3/detail/epilogue.hpp>
191
192#endif // RANGES_V3_DETAIL_BIND_BACK_HPP
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition meta.hpp:541
Tiny meta-programming library.
Definition bind_back.hpp:170
Definition bind_back.hpp:37
constexpr invoke_result_t< Fn const &, CallArgs..., Args const &... > operator()(CallArgs &&... cargs) const &noexcept(is_nothrow_invocable_v< Fn const &, CallArgs..., Args const &... >)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition bind_back.hpp:71
constexpr invoke_result_t< Fn &, CallArgs..., Args &... > operator()(CallArgs &&... cargs) &noexcept(is_nothrow_invocable_v< Fn &, CallArgs..., Args &... >)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition bind_back.hpp:58