1 #ifndef _SIGC_ADAPTORS_BIND_H_
2 #define _SIGC_ADAPTORS_BIND_H_
3 #include <sigc++/adaptors/adaptor_trait.h>
4 #include <sigc++/adaptors/bound_argument.h>
6 #include <sigc++/tuple-utils/tuple_for_each.h>
7 #include <sigc++/tuple-utils/tuple_start.h>
8 #include <sigc++/tuple-utils/tuple_end.h>
9 #include <sigc++/tuple-utils/tuple_transform_each.h>
14 /** @defgroup bind bind(), bind_return()
15 * sigc::bind() alters an arbitrary functor by fixing arguments to certain values.
16 * Up to 7 arguments can be bound at a time.
17 * For single argument binding, overloads of sigc::bind() are provided that let you
18 * specify the zero-based position of the argument to fix with the first template parameter.
19 * (A value of @p -1 fixes the last argument so sigc::bind<-1>() gives the same result as sigc::bind().)
20 * The types of the arguments can optionally be specified if not deduced.
24 * void foo(int, int, int);
25 * // single argument binding ...
26 * sigc::bind(&foo,1)(2,3); //fixes the last (third) argument and calls foo(2,3,1)
27 * sigc::bind<-1>(&foo,1)(2,3); //same as bind(&foo,1)(2,3) (calls foo(2,3,1))
28 * sigc::bind<0>(&foo,1)(2,3); //fixes the first argument and calls foo(1,2,3)
29 * sigc::bind<1>(&foo,1)(2,3); //fixes the second argument and calls foo(2,1,3)
30 * sigc::bind<2>(&foo,1)(2,3); //fixes the third argument and calls foo(2,3,1)
31 * // multi argument binding ...
32 * sigc::bind(&foo,1,2)(3); //fixes the last two arguments and calls foo(3,1,2)
33 * sigc::bind(&foo,1,2,3)(); //fixes all three arguments and calls foo(1,2,3)
36 * The functor sigc::bind() returns can be passed into
37 * sigc::signal::connect() directly.
41 * sigc::signal<void()> some_signal;
43 * some_signal.connect(sigc::bind(&foo,1));
46 * sigc::bind_return() alters an arbitrary functor by
47 * fixing its return value to a certain value.
52 * std::cout << sigc::bind_return(&foo, 5)(); // calls foo() and returns 5
55 * You can bind references to functors by passing the objects through
56 * the std::ref() helper function.
61 * sigc::signal<void()> some_signal;
63 * some_signal.connect(sigc::bind(&foo, std::ref(some_int)));
66 * If you bind an object of a sigc::trackable derived type to a functor
67 * by reference, a slot assigned to the bind adaptor is cleared automatically
68 * when the object goes out of scope.
72 * struct bar : public sigc::trackable {} some_bar;
73 * sigc::signal<void()> some_signal;
75 * some_signal.connect(sigc::bind(&foo, std::ref(some_bar)));
76 * // disconnected automatically if some_bar goes out of scope
85 template <class T_element>
86 struct TransformEachInvoker
88 //We take T_element as non-const because invoke() is not const.
89 //TODO: Take element as T_element&& ?
93 transform(T_element& element) {
94 return element.invoke();
98 } //namespace internal
100 /** Adaptor that binds arguments to the wrapped functor.
101 * Use the convenience function sigc::bind() to create an instance of sigc::bind_functor.
103 * The following template arguments are used:
104 * - @e I_location Zero-based position of the argument to fix (@p -1 for the last argument).
105 * - @e T_bound Types of the bound argument.
106 * - @e T_functor Type of the functor to wrap.
110 template <int I_location, class T_functor, class... T_bound>
111 struct bind_functor : public adapts<T_functor>
113 using adaptor_type = typename adapts<T_functor>::adaptor_type;
114 using result_type = typename adaptor_type::result_type;
116 /** Invokes the wrapped functor passing on the arguments.
117 * bound_ is passed as the next argument.
118 * @param _A_arg Arguments to be passed on to the functor.
119 * @return The return value of the functor invocation.
121 template <class... T_arg>
123 operator()(T_arg&&... _A_arg)
125 //For instance, if I_location is 1, and _A_arg has 4 arguments,
126 //we would want to call operator() with (_A_arg0, bound, _A_arg1, _A_arg2).
128 using tuple_type_args = std::tuple<type_trait_pass_t<T_arg>...>;
129 const auto t_args = std::tuple<T_arg...>(std::forward<T_arg>(_A_arg)...);
130 constexpr auto t_args_size = std::tuple_size<tuple_type_args>::value;
132 //Prevent calling tuple_start<> with values that will cause a compilation error.
133 static_assert(I_location <= t_args_size,
134 "I_location must be less than or equal to the number of arguments.");
136 const auto t_start = internal::tuple_start<I_location>(t_args);
137 const auto t_bound = internal::tuple_transform_each<internal::TransformEachInvoker>(bound_);
138 const auto t_end = internal::tuple_end<t_args_size - I_location>(t_args);
139 const auto t_with_bound = std::tuple_cat(t_start, t_bound, t_end);
141 constexpr const auto seq = std::make_index_sequence<std::tuple_size<decltype(t_with_bound)>::value>();
142 return call_functor_operator_parentheses(t_with_bound, seq);
145 /** Constructs a bind_functor object that binds an argument to the passed functor.
146 * @param _A_func Functor to invoke from operator()().
147 * @param _A_bound Argument to bind to the functor.
149 bind_functor(type_trait_take_t<T_functor> _A_func, type_trait_take_t<T_bound>... _A_bound)
150 : adapts<T_functor>(_A_func), bound_(_A_bound...)
154 /// The arguments bound to the functor.
155 std::tuple<bound_argument<T_bound>...> bound_;
157 template<class T, std::size_t... Is>
159 call_functor_operator_parentheses(T&& tuple,
160 std::index_sequence<Is...>)
162 return (this->functor_)(std::get<Is>(std::forward<T>(tuple))...);
167 /** Adaptor that binds argument(s) to the wrapped functor.
168 * This template specialization fixes the last argument(s) of the wrapped functor.
172 template <class T_functor, class... T_type>
173 struct bind_functor<-1, T_functor, T_type...> : public adapts<T_functor>
175 using adaptor_type = typename adapts<T_functor>::adaptor_type;
176 using result_type = typename adaptor_type::result_type;
178 /** Invokes the wrapped functor passing on the arguments.
179 * bound_ is passed as the next argument.
180 * @param _A_arg Arguments to be passed on to the functor.
181 * @return The return value of the functor invocation.
183 template <class... T_arg>
185 operator()(T_arg&&... _A_arg)
187 //For instance, if _A_arg has 4 arguments,
188 //we would want to call operator() with (_A_arg0, _A_arg1, _A_arg2, bound).
190 const auto t_args = std::tuple<T_arg...>(std::forward<T_arg>(_A_arg)...);
191 const auto t_bound = internal::tuple_transform_each<internal::TransformEachInvoker>(bound_);
192 const auto t_with_bound = std::tuple_cat(t_args, t_bound);
194 constexpr auto seq = std::make_index_sequence<std::tuple_size<decltype(t_with_bound)>::value>();
195 return call_functor_operator_parentheses(t_with_bound, seq);
198 /** Constructs a bind_functor object that binds an argument to the passed functor.
199 * @param _A_func Functor to invoke from operator()().
200 * @param _A_bound Arguments to bind to the functor.
202 bind_functor(type_trait_take_t<T_functor> _A_func, type_trait_take_t<T_type>... _A_bound)
203 : adapts<T_functor>(_A_func), bound_(_A_bound...)
206 /// The argument bound to the functor.
207 std::tuple<bound_argument<T_type>...> bound_;
210 template<class T, std::size_t... Is>
212 call_functor_operator_parentheses(T&& tuple,
213 std::index_sequence<Is...>)
215 return (this->functor_)(std::get<Is>(std::forward<T>(tuple))...);
222 //TODO: Avoid duplication with TrackObjVisitForEach in track_obj.h
223 template<typename T_element>
224 struct TupleVisitorVisitEach
226 template<typename T_action>
230 visit(const T_element& element, const T_action& action)
232 sigc::visit_each(action, element);
236 } //anonymous namespace
238 #ifndef DOXYGEN_SHOULD_SKIP_THIS
239 //template specialization of visitor<>::do_visit_each<>(action, functor):
240 /** Performs a functor on each of the targets of a functor.
241 * The function overload for sigc::bind_functor performs a functor on the
242 * functor and on the object instances stored in the sigc::bind_functor object.
246 template <int T_loc, class T_functor, class... T_bound>
247 struct visitor<bind_functor<T_loc, T_functor, T_bound...> >
249 template <class T_action>
250 static void do_visit_each(const T_action& _A_action,
251 const bind_functor<T_loc, T_functor, T_bound...>& _A_target)
253 sigc::visit_each(_A_action, _A_target.functor_);
254 sigc::visit_each(_A_action, std::get<0>(_A_target.bound_));
258 //template specialization of visitor<>::do_visit_each<>(action, functor):
259 /** Performs a functor on each of the targets of a functor.
260 * The function overload for sigc::bind_functor performs a functor on the
261 * functor and on the object instances stored in the sigc::bind_functor object.
265 template <class T_functor, class... T_type>
266 struct visitor<bind_functor<-1, T_functor, T_type...> >
268 template <typename T_action>
269 static void do_visit_each(const T_action& _A_action,
270 const bind_functor<-1, T_functor, T_type...>& _A_target)
272 sigc::visit_each(_A_action, _A_target.functor_);
274 sigc::internal::tuple_for_each<TupleVisitorVisitEach>(_A_target.bound_, _A_action);
278 #endif // DOXYGEN_SHOULD_SKIP_THIS
280 /** Creates an adaptor of type sigc::bind_functor which binds the passed argument to the passed functor.
281 * The optional template argument @e I_location specifies the zero-based
282 * position of the argument to be fixed (@p -1 stands for the last argument).
284 * @param _A_func Functor that should be wrapped.
285 * @param _A_b1 Argument to bind to @e _A_func.
286 * @return Adaptor that executes @e _A_func with the bound argument on invokation.
290 template <int I_location, class T_functor, class... T_bound>
291 inline decltype(auto)
292 bind(const T_functor& _A_func, T_bound... _A_b)
294 return bind_functor<I_location, T_functor, T_bound...>
298 /** Creates an adaptor of type sigc::bind_functor which fixes the last arguments of the passed functor.
299 * This function overload fixes the last arguments of @e _A_func.
301 * @param _A_func Functor that should be wrapped.
302 * @param _A_b Arguments to bind to @e _A_func.
303 * @return Adaptor that executes _A_func with the bound argument on invokation.
307 template <class T_functor, class... T_type>
308 inline decltype(auto)
309 bind(const T_functor& _A_func, T_type... _A_b)
310 { return bind_functor<-1, T_functor, T_type...>(_A_func, _A_b...);
314 } /* namespace sigc */
316 #endif /* _SIGC_ADAPTORS_BIND_H_ */