]> git.tdb.fi Git - ext/sigc++-2.0.git/blob - sigc++/adaptors/macros/bind.h.m4
Import libsigc++ 2.10.8 sources
[ext/sigc++-2.0.git] / sigc++ / adaptors / macros / bind.h.m4
1 dnl Copyright 2002, The libsigc++ Development Team
2 dnl
3 dnl This library is free software; you can redistribute it and/or
4 dnl modify it under the terms of the GNU Lesser General Public
5 dnl License as published by the Free Software Foundation; either
6 dnl version 2.1 of the License, or (at your option) any later version.
7 dnl
8 dnl This library is distributed in the hope that it will be useful,
9 dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
10 dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 dnl Lesser General Public License for more details.
12 dnl
13 dnl You should have received a copy of the GNU Lesser General Public
14 dnl License along with this library; if not, write to the Free Software
15 dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 dnl
17 divert(-1)
18
19 include(template.macros.m4)
20
21 define([ORDINAL],[dnl
22 $1[]ifelse($1,1,[st],$1,2,[nd],$1,3,[rd],[th])[]dnl
23 ])
24 define([DEDUCE_RESULT_TYPE_COUNT],[dnl
25   template <LOOP(class T_arg%1, eval(CALL_SIZE))>
26   struct deduce_result_type_internal<LIST($2, LOOP(T_arg%1,eval(CALL_SIZE)))>
27     { typedef typename adaptor_type::template deduce_result_type<LIST(LOOP(_P_(T_arg%1), eval(CALL_SIZE-$2)), LOOP(_P_(typename unwrap_reference<T_type%1>::type), $1))>::type type; };
28 ])
29 define([BIND_OPERATOR_LOCATION],[dnl
30 ifelse($2,1,,[dnl
31   /** Invokes the wrapped functor passing on the arguments.
32    * bound_ is passed as the ORDINAL($1) argument.dnl
33 FOR(1, eval($2-1),[
34    * @param _A_arg%1 Argument to be passed on to the functor.])
35    * @return The return value of the functor invocation.
36    */
37   template <LOOP([class T_arg%1], eval($2-1))>
38   typename deduce_result_type<LOOP(T_arg%1,eval($2-1))>::type
39   operator()(LOOP(T_arg%1 _A_arg%1,eval($2-1)))
40     { return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES<LIST(LOOP([_P_(T_arg%1)],eval($1-1)), _P_(typename unwrap_reference<T_bound>::type), FOR($1,eval($2-1),[_P_(T_arg%1),]))>
41         (LIST(LOOP(_A_arg%1,eval($1-1)), bound_.invoke(), FOR($1,eval($2-1),[_A_arg%1,])));
42     }
43
44   #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD
45   template <LOOP([class T_arg%1], eval($2-1))>
46   typename deduce_result_type<LOOP(T_arg%1,eval($2-1))>::type
47   sun_forte_workaround(LOOP(T_arg%1 _A_arg%1,eval($2-1)))
48     { return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES<LIST(LOOP([_P_(T_arg%1)],eval($1-1)), _P_(typename unwrap_reference<T_bound>::type), FOR($1,eval($2-1),[_P_(T_arg%1),]))>
49         (LIST(LOOP(_A_arg%1,eval($1-1)), bound_.invoke(), FOR($1,eval($2-1),[_A_arg%1,])));
50     }
51   #endif
52
53 ])dnl
54 ])
55 define([BIND_OPERATOR_COUNT],[dnl
56   /** Invokes the wrapped functor passing on the arguments.
57    * The last $1 argument(s) are fixed.dnl
58 FOR(1, eval($2-1),[
59    * @param _A_arg%1 Argument to be passed on to the functor.])
60    * @return The return value of the functor invocation.
61    */
62   template <LOOP([class T_arg%1], eval($2-1))>
63   typename deduce_result_type<LOOP(T_arg%1,eval($2-1))>::type
64   operator()(LOOP(T_arg%1 _A_arg%1, eval($2-1)))
65     { return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES<LIST(LOOP([_P_(T_arg%1)],eval($2-1)), LOOP(_P_(typename unwrap_reference<T_type%1>::type), $1))>
66         (LIST(LOOP(_A_arg%1,eval($2-1)), LOOP(bound%1_.invoke(), $1)));
67     }
68
69   #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD
70   template <LOOP([class T_arg%1], eval($2-1))>
71   typename deduce_result_type<LOOP(T_arg%1,eval($2-1))>::type
72   sun_forte_workaround(LOOP(T_arg%1 _A_arg%1, eval($2-1)))
73     { return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES<LIST(LOOP([_P_(T_arg%1)],eval($2-1)), LOOP(_P_(typename unwrap_reference<T_type%1>::type), $1))>
74         (LIST(LOOP(_A_arg%1,eval($2-1)), LOOP(bound%1_.invoke(), $1)));
75     }
76   #endif
77
78 ])
79 define([BIND_FUNCTOR_LOCATION],[dnl
80 ifelse($1,1,[#ifndef DOXYGEN_SHOULD_SKIP_THIS
81 ],)dnl Include only the first template specialization in the documentation. ($1 = 0..CALL_SIZE-1)
82 /** Adaptor that binds an argument to the wrapped functor.
83  * This template specialization fixes the ORDINAL(eval($1+1)) argument of the wrapped functor.
84  *
85  * @ingroup bind
86  */
87 template <class T_functor, class T_bound>
88 struct bind_functor<$1, T_functor, T_bound, LIST(LOOP(nil, CALL_SIZE - 1))> : public adapts<T_functor>
89 {
90   typedef typename adapts<T_functor>::adaptor_type adaptor_type;
91
92 ifelse($1,0,[#ifndef DOXYGEN_SHOULD_SKIP_THIS
93 ],)dnl
94   template <LOOP(class T_arg%1=void, eval(CALL_SIZE))>
95   struct deduce_result_type
96     { typedef typename adaptor_type::template deduce_result_type<LIST(LOOP(_P_(T_arg%1),eval($1)), _P_(typename unwrap_reference<T_bound>::type), FOR(eval($1+1),eval(CALL_SIZE-1),[_P_(T_arg%1),]))>::type type; };
97 ifelse($1,0,[#endif
98 ],)dnl
99   typedef typename adaptor_type::result_type  result_type;
100
101   /** Invokes the wrapped functor passing on the bound argument only.
102    * @return The return value of the functor invocation.
103    */
104   result_type
105   operator()()
106   {
107     //Note: The AIX compiler sometimes gives linker errors if we do not define this in the class.
108     return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES<_P_(typename unwrap_reference<T_bound>::type)> (bound_.invoke());
109   }
110
111 FOR(eval($1+1),CALL_SIZE,[[BIND_OPERATOR_LOCATION(eval($1+1),%1)]])dnl
112   /** Constructs a bind_functor object that binds an argument to the passed functor.
113    * @param _A_func Functor to invoke from operator()().
114    * @param _A_bound Argument to bind to the functor.
115    */
116   bind_functor(_R_(T_functor) _A_func, _R_(T_bound) _A_bound)
117     : adapts<T_functor>(_A_func), bound_(_A_bound)
118     {}
119
120   /// The argument bound to the functor.
121   bound_argument<T_bound> bound_;
122 };
123 ifelse($1,eval(CALL_SIZE-1),[#endif // DOXYGEN_SHOULD_SKIP_THIS
124 ],)dnl Include only the first template specialization in the documentation. ($1 = 0..CALL_SIZE-1)
125
126 ])dnl end BIND_FUNCTOR_LOCATION
127
128 define([BIND_FUNCTOR_COUNT],[dnl
129 /** Adaptor that binds $1 argument(s) to the wrapped functor.
130  * This template specialization fixes the last $1 argument(s) of the wrapped functor.
131  *
132  * @ingroup bind
133  */
134 template <LIST(class T_functor, LOOP(class T_type%1, $1))>
135 struct bind_functor<LIST(-1, T_functor, LIST(LOOP(T_type%1, $1), LOOP(nil, CALL_SIZE - $1)))> : public adapts<T_functor>
136 {
137   typedef typename adapts<T_functor>::adaptor_type adaptor_type;
138
139 ifelse($1,1,[#ifndef DOXYGEN_SHOULD_SKIP_THIS
140 ],)dnl
141   template <LIST(int count, LOOP(class T_arg%1, eval(CALL_SIZE)))>
142   struct deduce_result_type_internal
143     { typedef typename adaptor_type::template deduce_result_type<LIST(LOOP(_P_(T_arg%1), eval(CALL_SIZE-$1)), LOOP(_P_(typename unwrap_reference<T_type%1>::type), $1))>::type type; };
144 FOR(eval($1+1),eval(CALL_SIZE-1),[[DEDUCE_RESULT_TYPE_COUNT($1,%1)]])dnl
145
146   template <LOOP(class T_arg%1=void, eval(CALL_SIZE))>
147   struct deduce_result_type {
148     typedef typename deduce_result_type_internal<internal::count_void<LOOP(T_arg%1, eval(CALL_SIZE))>::value,
149                                                  LOOP(T_arg%1, eval(CALL_SIZE))>::type type;
150   };
151 ifelse($1,1,[#endif // DOXYGEN_SHOULD_SKIP_THIS
152 ],)dnl
153   typedef typename adaptor_type::result_type  result_type;
154
155   /** Invokes the wrapped functor passing on the bound argument only.
156    * @return The return value of the functor invocation.
157    */
158   result_type
159   operator()()
160   {
161     //Note: The AIX compiler sometimes gives linker errors if we do not define this in the class.
162     return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES<LOOP(_P_(typename unwrap_reference<T_type%1>::type), $1)> (LOOP(bound%1_.invoke(), $1));
163   }
164
165 FOR(2,eval(CALL_SIZE-$1+1),[[BIND_OPERATOR_COUNT($1,%1)]])dnl
166   /** Constructs a bind_functor object that binds an argument to the passed functor.
167    * @param _A_func Functor to invoke from operator()().dnl
168 FOR(1,$1,[
169    * @param _A_bound%1 Argument to bind to the functor.])
170    */
171   bind_functor(_R_(T_functor) _A_func, LOOP(_R_(T_type%1) _A_bound%1, $1))
172     : adapts<T_functor>(_A_func), LOOP(bound%1_(_A_bound%1), $1)
173     {}
174
175   /// The argument bound to the functor.dnl
176 FOR(1,$1,[
177   bound_argument<T_type%1> bound%1_;])
178 };
179
180 ifelse($1,1,[#ifndef DOXYGEN_SHOULD_SKIP_THIS
181 ],)dnl Include only the first template specialization of bind_functor and no
182 dnl template specialization of visitor in the documentation. ($1 = 1..CALL_SIZE)
183 //template specialization of visitor<>::do_visit_each<>(action, functor):
184 /** Performs a functor on each of the targets of a functor.
185  * The function overload for sigc::bind_functor performs a functor on the
186  * functor and on the object instances stored in the sigc::bind_functor object.
187  *
188  * @ingroup bind
189  */
190 template <class T_functor, LOOP(class T_type%1, $1)>
191 struct visitor<bind_functor<-1, T_functor, LOOP(T_type%1, $1)> >
192 {
193   template <typename T_action>
194   static void do_visit_each(const T_action& _A_action,
195                             const bind_functor<-1, T_functor,  LOOP(T_type%1, $1)>& _A_target)
196   {
197     sigc::visit_each(_A_action, _A_target.functor_);dnl
198 FOR(1,$1,[
199     sigc::visit_each(_A_action, _A_target.bound%1_);])
200   }
201 };
202 ifelse($1,CALL_SIZE,[#endif // DOXYGEN_SHOULD_SKIP_THIS
203 ],)dnl
204
205 ])dnl end BIND_FUNCTOR_COUNT
206
207 define([BIND_COUNT],[dnl
208 /** Creates an adaptor of type sigc::bind_functor which fixes the last $1 argument(s) of the passed functor.
209  * This function overload fixes the last $1 argument(s) of @e _A_func.
210  *
211  * @param _A_func Functor that should be wrapped.dnl
212 FOR(1,$1,[
213  * @param _A_b%1 Argument to bind to @e _A_func.])
214  * @return Adaptor that executes _A_func with the bound argument on invokation.
215  *
216  * @ingroup bind
217  */
218 template <LIST(LOOP(class T_type%1, $1), class T_functor)>
219 inline bind_functor<-1, T_functor,dnl
220 FOR(1,eval($1-1),[
221                     T_type%1,])
222                     T_type$1>
223 bind(const T_functor& _A_func, LOOP(T_type%1 _A_b%1, $1))
224 { return bind_functor<-1, T_functor,dnl
225 FOR(1,eval($1-1),[
226                     T_type%1,])
227                     T_type$1>
228                     (_A_func, LOOP(_A_b%1, $1));
229 }
230
231 ])
232
233 divert(0)dnl
234 _FIREWALL([ADAPTORS_BIND])
235 #include <sigc++/adaptors/adaptor_trait.h>
236 #include <sigc++/adaptors/bound_argument.h>
237
238 //TODO: See comment in functor_trait.h.
239 #if defined(nil) && defined(SIGC_PRAGMA_PUSH_POP_MACRO)
240   #define SIGC_NIL_HAS_BEEN_PUSHED 1
241   #pragma push_macro("nil")
242   #undef nil
243 #endif
244
245 namespace sigc {
246
247 #ifndef DOXYGEN_SHOULD_SKIP_THIS
248
249 namespace internal {
250
251 template <class T_arg1,class T_arg2,class T_arg3,class T_arg4,class T_arg5,class T_arg6,class T_arg7>
252 struct count_void
253   { static const int value=0; };
254 template <class T_arg1,class T_arg2,class T_arg3,class T_arg4,class T_arg5,class T_arg6>
255 struct count_void<T_arg1,T_arg2,T_arg3,T_arg4,T_arg5,T_arg6,void>
256   { static const int value=1; };
257 template <class T_arg1,class T_arg2,class T_arg3,class T_arg4,class T_arg5>
258 struct count_void<T_arg1,T_arg2,T_arg3,T_arg4,T_arg5,void,void>
259   { static const int value=2; };
260 template <class T_arg1,class T_arg2,class T_arg3,class T_arg4>
261 struct count_void<T_arg1,T_arg2,T_arg3,T_arg4,void,void,void>
262   { static const int value=3; };
263 template <class T_arg1,class T_arg2,class T_arg3>
264 struct count_void<T_arg1,T_arg2,T_arg3,void,void,void,void>
265   { static const int value=4; };
266 template <class T_arg1,class T_arg2>
267 struct count_void<T_arg1,T_arg2,void,void,void,void,void>
268   { static const int value=5; };
269 template <class T_arg1>
270 struct count_void<T_arg1,void,void,void,void,void,void>
271   { static const int value=6; };
272 template <>
273 struct count_void<void,void,void,void,void,void,void>
274   { static const int value=7; };
275
276 } /* namespace internal */
277
278 #endif /*DOXYGEN_SHOULD_SKIP_THIS*/
279
280
281 /** @defgroup bind bind(), bind_return()
282  * sigc::bind() alters an arbitrary functor by fixing arguments to certain values.
283  * Up to CALL_SIZE arguments can be bound at a time.
284  * For single argument binding, overloads of sigc::bind() are provided that let you
285  * specify the zero-based position of the argument to fix with the first template parameter.
286  * (A value of @p -1 fixes the last argument so sigc::bind<-1>() gives the same result as sigc::bind().)
287  * The types of the arguments can optionally be specified if not deduced.
288  *
289  * @par Examples:
290  * @code
291  * void foo(int, int, int);
292  * // single argument binding ...
293  * sigc::bind(&foo,1)(2,3);     //fixes the last (third) argument and calls foo(2,3,1)
294  * sigc::bind<-1>(&foo,1)(2,3); //same as bind(&foo,1)(2,3) (calls foo(2,3,1))
295  * sigc::bind<0>(&foo,1)(2,3);  //fixes the first argument and calls foo(1,2,3)
296  * sigc::bind<1>(&foo,1)(2,3);  //fixes the second argument and calls foo(2,1,3)
297  * sigc::bind<2>(&foo,1)(2,3);  //fixes the third argument and calls foo(2,3,1)
298  * // multi argument binding ...
299  * sigc::bind(&foo,1,2)(3);     //fixes the last two arguments and calls foo(3,1,2)
300  * sigc::bind(&foo,1,2,3)();    //fixes all three arguments and calls foo(1,2,3)
301  * @endcode
302  *
303  * The functor sigc::bind() returns can be passed into
304  * sigc::signal::connect() directly.
305  *
306  * @par Example:
307  * @code
308  * sigc::signal<void> some_signal;
309  * void foo(int);
310  * some_signal.connect(sigc::bind(&foo,1));
311  * @endcode
312  *
313  * sigc::bind_return() alters an arbitrary functor by
314  * fixing its return value to a certain value.
315  *
316  * @par Example:
317  * @code
318  * void foo();
319  * std::cout << sigc::bind_return(&foo, 5)(); // calls foo() and returns 5
320  * @endcode
321  *
322  * You can bind references to functors by passing the objects through
323  * the std::ref() or std::cref() functions.
324  *
325  * @par Example:
326  * @code
327  * int some_int;
328  * sigc::signal<void> some_signal;
329  * void foo(int&);
330  * some_signal.connect(sigc::bind(&foo, std::ref(some_int)));
331  * @endcode
332  *
333  * If you bind an object of a sigc::trackable derived type to a functor
334  * by reference, a slot assigned to the bind adaptor is cleared automatically
335  * when the object goes out of scope.
336  *
337  * @par Example:
338  * @code
339  * struct bar : public sigc::trackable {} some_bar;
340  * sigc::signal<void> some_signal;
341  * void foo(bar&);
342  * some_signal.connect(sigc::bind(&foo, std::ref(some_bar)));
343  *   // disconnected automatically if some_bar goes out of scope
344  * @endcode
345  *
346  * @ingroup adaptors
347  */
348
349 /** Adaptor that binds an argument to the wrapped functor.
350  * Use the convenience function sigc::bind() to create an instance of sigc::bind_functor.
351  *
352  * The following template arguments are used:
353  * - @e I_location Zero-based position of the argument to fix (@p -1 for the last argument).dnl
354 FOR(1, CALL_SIZE,[
355  * - @e T_type%1 Type of the [ORDINAL(%1)] bound argument.])
356  * - @e T_functor Type of the functor to wrap.
357  *
358  * @ingroup bind
359  */
360 template <LIST(int I_location, class T_functor, LOOP(class T_type%1=nil, CALL_SIZE))>
361 #ifndef DOXYGEN_SHOULD_SKIP_THIS
362 struct bind_functor;
363 #else
364 struct bind_functor {};
365 #endif
366
367 FOR(0,eval(CALL_SIZE-1),[[BIND_FUNCTOR_LOCATION(%1)]])dnl
368
369 #ifndef DOXYGEN_SHOULD_SKIP_THIS
370 //template specialization of visitor<>::do_visit_each<>(action, functor):
371 /** Performs a functor on each of the targets of a functor.
372  * The function overload for sigc::bind_functor performs a functor on the
373  * functor and on the object instances stored in the sigc::bind_functor object.
374  *
375  * @ingroup bind
376  */
377 template <int T_loc, class T_functor, class T_bound>
378 struct visitor<bind_functor<T_loc, T_functor, T_bound> >
379 {
380   template <class T_action>
381   static void do_visit_each(const T_action& _A_action,
382                             const bind_functor<T_loc, T_functor, T_bound>& _A_target)
383   {
384     sigc::visit_each(_A_action, _A_target.functor_);
385     sigc::visit_each(_A_action, _A_target.bound_);
386   }
387 };
388 #endif // DOXYGEN_SHOULD_SKIP_THIS
389
390 FOR(1,CALL_SIZE,[[BIND_FUNCTOR_COUNT(%1)]])dnl
391
392 /** Creates an adaptor of type sigc::bind_functor which binds the passed argument to the passed functor.
393  * The optional template argument @e I_location specifies the zero-based
394  * position of the argument to be fixed (@p -1 stands for the last argument).
395  *
396  * @param _A_func Functor that should be wrapped.
397  * @param _A_b1 Argument to bind to @e _A_func.
398  * @return Adaptor that executes @e _A_func with the bound argument on invokation.
399  *
400  * @ingroup bind
401  */
402 template <int I_location, class T_bound1, class T_functor>
403 inline bind_functor<I_location, T_functor, T_bound1>
404 bind(const T_functor& _A_func, T_bound1 _A_b1)
405 {
406   return bind_functor<I_location, T_functor, T_bound1>
407            (_A_func, _A_b1);
408 }
409
410 FOR(1,CALL_SIZE,[[BIND_COUNT(%1)]])dnl
411
412 } /* namespace sigc */
413
414 #ifdef SIGC_NIL_HAS_BEEN_PUSHED
415   #undef SIGC_NIL_HAS_BEEN_PUSHED
416   #pragma pop_macro("nil")
417 #endif