]> git.tdb.fi Git - ext/sigc++-2.0.git/blob - sigc++/macros/signal.h.m4
Import libsigc++ 2.10.8 sources
[ext/sigc++-2.0.git] / sigc++ / macros / signal.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([SIGNAL_EMIT_N],[dnl
22 /** Abstracts signal emission.
23  * This template implements the emit() function of signal$1.
24  * Template specializations are available to optimize signal
25  * emission when no accumulator is used, for example when the template
26  * argument @e T_accumulator is @p nil.
27  */
28 template <LIST(class T_return, LOOP(class T_arg%1, $1), class T_accumulator)>
29 struct signal_emit$1
30 {
31   typedef signal_emit$1<LIST(T_return, LOOP(T_arg%1, $1), T_accumulator)> self_type;
32   typedef typename T_accumulator::result_type result_type;
33   typedef slot<T_return(LIST(LOOP(T_arg%1, $1)))> slot_type;
34   typedef internal::slot_iterator_buf<self_type, T_return> slot_iterator_buf_type;
35   typedef internal::slot_reverse_iterator_buf<self_type, T_return> slot_reverse_iterator_buf_type;
36   typedef signal_impl::const_iterator_type iterator_type;
37
38 ifelse($1,0,,[dnl
39   /** Instantiates the class.
40    * The parameters are stored in member variables. operator()() passes
41    * the values on to some slot.
42    */
43 ])dnl
44   signal_emit$1(LOOP(type_trait_take_t<T_arg%1> _A_a%1, $1)) ifelse($1,0,,[
45     : LOOP(_A_a%1_(_A_a%1), $1)]) {}
46
47 ifelse($1,0,[dnl
48   /** Invokes a slot.],[
49   /** Invokes a slot using the buffered parameter values.])
50    * @param _A_slot Some slot to invoke.
51    * @return The slot's return value.
52    */
53   T_return operator()(const slot_type& _A_slot) const
54     { return (sigc::internal::function_pointer_cast<typename slot_type::call_type>(_A_slot.rep_->call_))(LIST(_A_slot.rep_, LOOP(_A_a%1_, $1))); }
55 dnl  T_return operator()(const slot_type& _A_slot) const
56 dnl    { return _A_slot(LOOP(_A_a%1_, $1)); }
57
58   /** Executes a list of slots using an accumulator of type @e T_accumulator.dnl
59 ifelse($1,0,,[
60    * The arguments are buffered in a temporary instance of signal_emit$1.])
61 FOR(1, $1,[
62    * @param _A_a%1 Argument to be passed on to the slots.])
63    * @return The accumulated return values of the slot invocations as processed by the accumulator.
64    */
65   static result_type emit(LIST(signal_impl* impl, LOOP(type_trait_take_t<T_arg%1> _A_a%1, $1)))
66     {
67       T_accumulator accumulator;
68
69       if (!impl)
70         return accumulator(slot_iterator_buf_type(), slot_iterator_buf_type());
71
72       signal_exec exec(impl);
73       temp_slot_list slots(impl->slots_);
74
75       self_type self ifelse($1,0,,[(LOOP(_A_a%1, $1))]);
76       return accumulator(slot_iterator_buf_type(slots.begin(), &self),
77                          slot_iterator_buf_type(slots.end(), &self));
78     }
79
80 _DEPRECATE_IFDEF_START
81   /** Executes a list of slots using an accumulator of type @e T_accumulator in reverse order.dnl
82 ifelse($1,0,,[
83    * The arguments are buffered in a temporary instance of signal_emit$1.])
84 FOR(1, $1,[
85    * @param _A_a%1 Argument to be passed on to the slots.])
86    * @return The accumulated return values of the slot invocations as processed by the accumulator.
87    *
88    * @deprecated This is apparently not useful, but please let us know if you need it.
89    */
90   static result_type emit_reverse(LIST(signal_impl* impl, LOOP(type_trait_take_t<T_arg%1> _A_a%1, $1)))
91     {
92       T_accumulator accumulator;
93
94       if (!impl)
95         return accumulator(slot_iterator_buf_type(), slot_iterator_buf_type());
96
97       signal_exec exec(impl);
98       temp_slot_list slots(impl->slots_);
99
100       self_type self ifelse($1,0,,[(LOOP(_A_a%1, $1))]);
101       return accumulator(slot_reverse_iterator_buf_type(slots.end(), &self),
102                          slot_reverse_iterator_buf_type(slots.begin(), &self));
103     }
104 _DEPRECATE_IFDEF_END
105
106 dnl
107   FOR(1, $1,[
108   type_trait_take_t<T_arg%1> _A_a%1_;])
109 };
110
111 /** Abstracts signal emission.
112  * This template specialization implements an optimized emit()
113  * function for the case that no accumulator is used.
114  */
115 template <LIST(class T_return, LOOP(class T_arg%1, $1))>
116 struct signal_emit$1<LIST(T_return, LOOP(T_arg%1, $1), nil)>
117 {
118   typedef signal_emit$1<LIST(T_return, LOOP(T_arg%1, $1), nil) > self_type;
119   typedef T_return result_type;
120   typedef slot<T_return(LIST(LOOP(T_arg%1, $1)))> slot_type;
121   typedef signal_impl::const_iterator_type iterator_type;
122   typedef typename slot_type::call_type call_type;
123
124   /** Executes a list of slots using an accumulator of type @e T_accumulator.dnl
125 ifelse($1,0,,[
126    * The arguments are passed directly on to the slots.])
127    * The return value of the last slot invoked is returned.
128    * @param first An iterator pointing to the first slot in the list.
129    * @param last An iterator pointing to the last slot in the list.dnl
130 FOR(1, $1,[
131    * @param _A_a%1 Argument to be passed on to the slots.])
132    * @return The return value of the last slot invoked.
133    */
134   static result_type emit(LIST(signal_impl* impl, LOOP(type_trait_take_t<T_arg%1> _A_a%1, $1)))
135     {
136       if (!impl || impl->slots_.empty())
137         return T_return();
138         
139       signal_exec exec(impl);
140       T_return r_ = T_return(); 
141       
142       //Use this scope to make sure that "slots" is destroyed before "exec" is destroyed.
143       //This avoids a leak on MSVC++ - see http://bugzilla.gnome.org/show_bug.cgi?id=306249
144       { 
145         temp_slot_list slots(impl->slots_);
146         auto it = slots.begin();
147         for (; it != slots.end(); ++it)
148           if (!it->empty() && !it->blocked()) break;
149           
150         if (it == slots.end())
151           return T_return(); // note that 'T_return r_();' doesn't work => define 'r_' after this line and initialize as follows:
152   
153         r_ = (sigc::internal::function_pointer_cast<call_type>(it->rep_->call_))(LIST(it->rep_, LOOP(_A_a%1, $1)));
154         for (++it; it != slots.end(); ++it)
155           {
156             if (it->empty() || it->blocked())
157               continue;
158             r_ = (sigc::internal::function_pointer_cast<call_type>(it->rep_->call_))(LIST(it->rep_, LOOP(_A_a%1, $1)));
159           }
160       }
161       
162       return r_;
163     }
164
165 _DEPRECATE_IFDEF_START
166   /** Executes a list of slots using an accumulator of type @e T_accumulator in reverse order.dnl
167 ifelse($1,0,,[
168    * The arguments are passed directly on to the slots.])
169    * The return value of the last slot invoked is returned.
170    * @param first An iterator pointing to the first slot in the list.
171    * @param last An iterator pointing to the last slot in the list.dnl
172 FOR(1, $1,[
173    * @param _A_a%1 Argument to be passed on to the slots.])
174    * @return The return value of the last slot invoked.
175    *
176    * @deprecated This is apparently not useful, but please let us know if you need it.
177    */
178   static result_type emit_reverse(LIST(signal_impl* impl, LOOP(type_trait_take_t<T_arg%1> _A_a%1, $1)))
179     {
180       if (!impl || impl->slots_.empty())
181         return T_return();
182         
183       signal_exec exec(impl);
184       T_return r_ = T_return(); 
185       
186       //Use this scope to make sure that "slots" is destroyed before "exec" is destroyed.
187       //This avoids a leak on MSVC++ - see http://bugzilla.gnome.org/show_bug.cgi?id=306249
188       { 
189 #ifndef SIGC_HAVE_SUN_REVERSE_ITERATOR
190         typedef std::reverse_iterator<signal_impl::iterator_type> reverse_iterator_type;
191 #else
192         typedef std::reverse_iterator<signal_impl::iterator_type, std::random_access_iterator_tag,
193                                        slot_base, slot_base&, slot_base*, std::ptrdiff_t> reverse_iterator_type;
194 #endif
195
196         temp_slot_list slots(impl->slots_);
197         reverse_iterator_type it(slots.end());
198         for (; it != reverse_iterator_type(slots.begin()); ++it)
199           if (!it->empty() && !it->blocked()) break;
200           
201         if (it == reverse_iterator_type(slots.begin()))
202           return T_return(); // note that 'T_return r_();' doesn't work => define 'r_' after this line and initialize as follows:
203   
204         r_ = (sigc::internal::function_pointer_cast<call_type>(it->rep_->call_))(LIST(it->rep_, LOOP(_A_a%1, $1)));
205         for (++it; it != reverse_iterator_type(slots.begin()); ++it)
206           {
207             if (it->empty() || it->blocked())
208               continue;
209             r_ = (sigc::internal::function_pointer_cast<call_type>(it->rep_->call_))(LIST(it->rep_, LOOP(_A_a%1, $1)));
210           }
211       }
212       
213       return r_;
214     }
215 _DEPRECATE_IFDEF_END
216 };
217
218 /** Abstracts signal emission.
219  * This template specialization implements an optimized emit()
220  * function for the case that no accumulator is used and the
221  * return type is @p void.
222  */
223 template <LOOP(class T_arg%1, $1)>
224 struct signal_emit$1<LIST(void, LOOP(T_arg%1, $1), nil)>
225 {
226   typedef signal_emit$1<LIST(void, LOOP(T_arg%1, $1), nil)> self_type;
227   typedef void result_type;
228   typedef slot<void(LIST(LOOP(T_arg%1, $1)))> slot_type;
229   typedef signal_impl::const_iterator_type iterator_type;
230   typedef ifelse($1,0,void (*call_type)(slot_rep*),typename slot_type::call_type call_type);
231
232   /** Executes a list of slots using an accumulator of type @e T_accumulator.dnl
233 ifelse($1,0,,[
234    * The arguments are passed directly on to the slots.])
235    * @param first An iterator pointing to the first slot in the list.
236    * @param last An iterator pointing to the last slot in the list.dnl
237 FOR(1, $1,[
238    * @param _A_a%1 Argument to be passed on to the slots.])
239    */
240   static result_type emit(LIST(signal_impl* impl, LOOP(type_trait_take_t<T_arg%1> _A_a%1, $1)))
241     {
242       if (!impl || impl->slots_.empty()) return;
243       signal_exec exec(impl);
244       temp_slot_list slots(impl->slots_);
245
246       for (const auto& slot : slots)
247         {
248           if (slot.empty() || slot.blocked())
249             continue;
250           (sigc::internal::function_pointer_cast<call_type>(slot.rep_->call_))(LIST(slot.rep_, LOOP(_A_a%1, $1)));
251         }
252     }
253
254 _DEPRECATE_IFDEF_START
255   /** Executes a list of slots using an accumulator of type @e T_accumulator in reverse order.dnl
256 ifelse($1,0,,[
257    * The arguments are passed directly on to the slots.])
258    * @param first An iterator pointing to the first slot in the list.
259    * @param last An iterator pointing to the last slot in the list.dnl
260 FOR(1, $1,[
261    * @param _A_a%1 Argument to be passed on to the slots.])
262    *
263    * @deprecated This is apparently not useful, but please let us know if you need it.
264    */
265   static result_type emit_reverse(LIST(signal_impl* impl, LOOP(type_trait_take_t<T_arg%1> _A_a%1, $1)))
266     {
267       if (!impl || impl->slots_.empty()) return;
268       signal_exec exec(impl);
269       temp_slot_list slots(impl->slots_);
270
271 #ifndef SIGC_HAVE_SUN_REVERSE_ITERATOR
272       typedef std::reverse_iterator<signal_impl::iterator_type> reverse_iterator_type;
273 #else
274       typedef std::reverse_iterator<signal_impl::iterator_type, std::random_access_iterator_tag,
275                                      slot_base, slot_base&, slot_base*, std::ptrdiff_t> reverse_iterator_type;
276 #endif
277       for (auto it = reverse_iterator_type(slots.end()); it != reverse_iterator_type(slots.begin()); ++it)
278         {
279           if (it->empty() || it->blocked())
280             continue;
281           (sigc::internal::function_pointer_cast<call_type>(it->rep_->call_))(LIST(it->rep_, LOOP(_A_a%1, $1)));
282         }
283     }
284 _DEPRECATE_IFDEF_END
285 };
286
287 ])
288 define([SIGNAL_N],[dnl
289 /** Signal declaration.
290  * signal$1 can be used to connect() slots that are invoked
291  * during subsequent calls to emit(). Any functor or slot
292  * can be passed into connect(). It is converted into a slot
293  * implicitly.
294  *
295  * If you want to connect one signal to another, use make_slot()
296  * to retrieve a functor that emits the signal when invoked.
297  *
298  * Be careful if you directly pass one signal into the connect()
299  * method of another: a shallow copy of the signal is made and
300  * the signal's slots are not disconnected until both the signal
301  * and its clone are destroyed, which is probably not what you want.
302  *
303  * The following template arguments are used:
304  * - @e T_return The desired return type for the emit() function (may be overridden by the accumulator).dnl
305 FOR(1,$1,[
306  * - @e T_arg%1 Argument type used in the definition of emit().])
307  * - @e T_accumulator The accumulator type used for emission. The default
308  * @p nil means that no accumulator should be used, for example if signal
309  * emission returns the return value of the last slot invoked.
310  *
311  * You should use the more convenient unnumbered sigc::signal template.
312  *
313  * @ingroup signal
314  */
315 template <LIST(class T_return, LOOP(class T_arg%1, $1), class T_accumulator=nil)>
316 class signal$1
317   : public signal_base
318 {
319 public:
320   typedef internal::signal_emit$1<LIST(T_return, LOOP(T_arg%1, $1), T_accumulator)> emitter_type;
321   typedef typename emitter_type::result_type         result_type;
322   typedef slot<T_return(LIST(LOOP(T_arg%1, $1)))>    slot_type;
323   typedef slot_list<slot_type>                       slot_list_type;
324   typedef typename slot_list_type::iterator               iterator;
325   typedef typename slot_list_type::const_iterator         const_iterator;
326   typedef typename slot_list_type::reverse_iterator       reverse_iterator;
327   typedef typename slot_list_type::const_reverse_iterator const_reverse_iterator;
328
329   /** Add a slot to the list of slots.
330    * Any functor or slot may be passed into connect().
331    * It will be converted into a slot implicitly.
332    * The returned iterator may be stored for disconnection
333    * of the slot at some later point. It stays valid until
334    * the slot is removed from the list of slots. The iterator
335    * can also be implicitly converted into a sigc::connection object
336    * that may be used safely beyond the life time of the slot.
337    *
338    * std::function<> and C++11 lambda expressions are functors.
339    * These are examples of functors that can be connected to a signal.
340    *
341    * %std::bind() creates a functor, but this functor typically has an
342    * %operator()() which is a variadic template.
343    * Our functor_trait can't deduce the result type
344    * of such a functor. If you first assign the return value of %std::bind()
345    * to a std::function, you can connect the std::function to a signal.
346    *
347    * @param slot_ The slot to add to the list of slots.
348    * @return An iterator pointing to the new slot in the list.
349    */
350   iterator connect(const slot_type& slot_)
351     { return iterator(signal_base::connect(static_cast<const slot_base&>(slot_))); }
352
353   /** Add a slot to the list of slots.
354    * @see connect(const slot_type& slot_).
355    *
356    * @newin{2,8}
357    */
358   iterator connect(slot_type&& slot_)
359     { return iterator(signal_base::connect(std::move(static_cast<slot_base&>(slot_)))); }
360
361   /** Triggers the emission of the signal.
362    * During signal emission all slots that have been connected
363    * to the signal are invoked unless they are manually set into
364    * a blocking state. The parameters are passed on to the slots.
365    * If @e T_accumulated is not @p nil, an accumulator of this type
366    * is used to process the return values of the slot invocations.
367    * Otherwise, the return value of the last slot invoked is returned.dnl
368 FOR(1, $1,[
369    * @param _A_a%1 Argument to be passed on to the slots.])
370    * @return The accumulated return values of the slot invocations.
371    */
372   result_type emit(LOOP(type_trait_take_t<T_arg%1> _A_a%1, $1)) const
373     { return emitter_type::emit(LIST(impl_, LOOP(_A_a%1, $1))); }
374
375 _DEPRECATE_IFDEF_START
376   /** Triggers the emission of the signal in reverse order (see emit()).
377    *
378    * @deprecated This is apparently not useful, but please let us know if you need it.
379    */
380   result_type emit_reverse(LOOP(type_trait_take_t<T_arg%1> _A_a%1, $1)) const
381     { return emitter_type::emit_reverse(LIST(impl_, LOOP(_A_a%1, $1))); }
382 _DEPRECATE_IFDEF_END
383
384   /** Triggers the emission of the signal (see emit()).
385    *
386    * @deprecated This is apparently not useful, but let us know if you need it.
387    */
388   result_type operator()(LOOP(type_trait_take_t<T_arg%1> _A_a%1, $1)) const
389     { return emit(LOOP(_A_a%1, $1)); }
390
391   /** Creates a functor that calls emit() on this signal.
392    * @code
393    * sigc::mem_fun(mysignal, &sigc::signal$1::emit)
394    * @endcode
395    * yields the same result.
396    * @return A functor that calls emit() on this signal.
397    */
398   bound_const_mem_functor$1<LIST(result_type, signal$1, LOOP(type_trait_take_t<T_arg%1>, $1))> make_slot() const
399     { return bound_const_mem_functor$1<LIST(result_type, signal$1, LOOP(type_trait_take_t<T_arg%1>, $1))>(*this, &signal$1::emit); }
400
401 _DEPRECATE_IFDEF_START
402   /** Creates an STL-style interface for the signal's list of slots.
403    * This interface supports iteration, insertion and removal of slots.
404    * @return An STL-style interface for the signal's list of slots.
405    *
406    * @deprecated This is apparently not useful, but please let us know if you need it.
407    */
408   slot_list_type slots()
409     { return slot_list_type(impl()); }
410
411   /** Creates an STL-style interface for the signal's list of slots.
412    * This interface supports iteration, insertion and removal of slots.
413    * @return An STL-style interface for the signal's list of slots.
414    *
415    * @deprecated This is apparently not useful, but please let us know if you need it.
416    */
417   const slot_list_type slots() const
418     { return slot_list_type(const_cast<signal$1*>(this)->impl()); }
419 _DEPRECATE_IFDEF_END
420
421   signal$1() {}
422
423   signal$1(const signal$1& src)
424     : signal_base(src) {}
425
426   signal$1(signal$1&& src)
427     : signal_base(std::move(src)) {}
428
429   signal$1& operator=(const signal$1& src)
430   {
431     signal_base::operator=(src);
432     return *this;
433   }
434
435   signal$1& operator=(signal$1&& src)
436   {
437     signal_base::operator=(std::move(src));
438     return *this;
439   }
440 };
441
442 ])
443 define([SIGNAL],[dnl
444 ifelse($1, $2,[dnl
445 /** Convenience wrapper for the numbered sigc::signal# templates.
446  * signal can be used to connect() slots that are invoked
447  * during subsequent calls to emit(). Any functor or slot
448  * can be passed into connect(). It is converted into a slot
449  * implicitly.
450  *
451  * If you want to connect one signal to another, use make_slot()
452  * to retrieve a functor that emits the signal when invoked.
453  *
454  * Be careful if you directly pass one signal into the connect()
455  * method of another: a shallow copy of the signal is made and
456  * the signal's slots are not disconnected until both the signal
457  * and its clone are destroyed, which is probably not what you want!
458  *
459  * The template arguments determine the function signature of
460  * the emit() function:
461  * - @e T_return The desired return type of the emit() function.dnl
462 FOR(1,$1,[
463  * - @e T_arg%1 Argument type used in the definition of emit(). The default @p nil means no argument.])
464  *
465  * To specify an accumulator type the nested class signal::accumulated can be used.
466  *
467  * @par Example:
468  * @code
469  * void foo(int) {}
470  * sigc::signal<void, long> sig;
471  * sig.connect(sigc::ptr_fun(&foo));
472  * sig.emit(19);
473  * @endcode
474  *
475  * @deprecated Please use the syntax similar to that used by std::function<>:
476  * @code
477  * sigc::slot<void(bool, int)> some_slot;
478  * @endcode
479  *
480  * @ingroup signal
481  */
482 template <LIST(class T_return, LOOP(class T_arg%1 = nil, $1))>
483 class signal],[dnl
484
485 /** Convenience wrapper for the numbered sigc::signal$1 template.
486  * See the base class for useful methods.
487  * This is the template specialization of the unnumbered sigc::signal
488  * template for $1 argument(s).
489  *
490  * @deprecated Please use the syntax similar to that used by std::function<>:
491  * @code
492  * sigc::slot<void(bool, int)> some_slot;
493  * @endcode
494 ifelse($1, $2,[dnl
495  *
496  * @ingroup signal
497 ])dnl
498  */
499 template <LIST(class T_return, LOOP(class T_arg%1, $1))>
500 class signal ifelse($1, $2,,[<LIST(T_return, LOOP(T_arg%1,$1), LOOP(nil, CALL_SIZE - $1))>])])
501   : public signal$1<LIST(T_return, LOOP(T_arg%1, $1),nil)>
502 {
503 public:
504 ifelse($1, $2,[dnl
505   /** Convenience wrapper for the numbered sigc::signal# templates.
506    * Like sigc::signal but the additional template parameter @e T_accumulator
507    * defines the accumulator type that should be used.
508    *
509    * An accumulator is a functor that uses a pair of special iterators
510    * to step through a list of slots and calculate a return value
511    * from the results of the slot invokations. The iterators' operator*()
512    * executes the slot. The return value is buffered, so that in an expression
513    * like @code a = (*i) * (*i); @endcode the slot is executed only once.
514    * The accumulator must define its return value as @p result_type.
515    * 
516    * @par Example 1:
517    * This accumulator calculates the arithmetic mean value:
518    * @code
519    * struct arithmetic_mean_accumulator
520    * {
521    *   typedef double result_type;
522    *   template<typename T_iterator>
523    *   result_type operator()(T_iterator first, T_iterator last) const
524    *   {
525    *     result_type value_ = 0;
526    *     int n_ = 0;
527    *     for (; first != last; ++first, ++n_)
528    *       value_ += *first;
529    *     return value_ / n_;
530    *   }
531    * };
532    * @endcode
533    *
534    * @par Example 2:
535    * This accumulator stops signal emission when a slot returns zero:
536    * @code
537    * struct interruptable_accumulator
538    * {
539    *   typedef bool result_type;
540    *   template<typename T_iterator>
541    *   result_type operator()(T_iterator first, T_iterator last) const
542    *   {
543    *     for (; first != last; ++first, ++n_)
544    *       if (!*first) return false;
545    *     return true;
546    *   }
547    * };
548    * @endcode
549    *
550    * @ingroup signal
551 ],[
552   /** Convenience wrapper for the numbered sigc::signal$1 template.
553    * Like sigc::signal but the additional template parameter @e T_accumulator
554    * defines the accumulator type that should be used.
555 ])dnl
556    */
557   template <class T_accumulator>
558   class accumulated
559     : public signal$1<LIST(T_return, LOOP(T_arg%1, $1), T_accumulator)>
560   {
561   public:
562     accumulated() {}
563     accumulated(const accumulated& src)
564       : signal$1<LIST(T_return, LOOP(T_arg%1, $1), T_accumulator)>(src) {}
565   };
566
567   signal() {}
568
569   signal(const signal& src)
570     : signal$1<LIST(T_return, LOOP(T_arg%1, $1),nil)>(src) {}
571
572   signal(signal&& src)
573     : signal$1<LIST(T_return, LOOP(T_arg%1, $1),nil)>(std::move(src)) {}
574
575   signal& operator=(const signal& src)
576   {
577     signal$1<LIST(T_return, LOOP(T_arg%1, $1),nil)>::operator=(src);
578     return *this;
579   }
580
581   signal& operator=(signal&& src)
582   {
583     signal$1<LIST(T_return, LOOP(T_arg%1, $1),nil)>::operator=(std::move(src));
584     return *this;
585   }
586 };
587
588 /**
589  * This specialization allow use of the  sigc::signal<R(Args...)> syntax,
590  */
591 template <LIST(class T_return, LOOP(class T_arg%1, $1))>
592 class signal<T_return(LIST(LOOP(T_arg%1, $1)))>
593   : public signal$1<LIST(T_return, LOOP(T_arg%1, $1),nil)>
594 {
595 public:
596 ifelse($1, $2,[dnl
597   /** Convenience wrapper for the numbered sigc::signal# templates.
598    * Like sigc::signal but the additional template parameter @e T_accumulator
599    * defines the accumulator type that should be used.
600    *
601    * An accumulator is a functor that uses a pair of special iterators
602    * to step through a list of slots and calculate a return value
603    * from the results of the slot invokations. The iterators' operator*()
604    * executes the slot. The return value is buffered, so that in an expression
605    * like @code a = (*i) * (*i); @endcode the slot is executed only once.
606    * The accumulator must define its return value as @p result_type.
607    *
608    * @par Example 1:
609    * This accumulator calculates the arithmetic mean value:
610    * @code
611    * struct arithmetic_mean_accumulator
612    * {
613    *   typedef double result_type;
614    *   template<typename T_iterator>
615    *   result_type operator()(T_iterator first, T_iterator last) const
616    *   {
617    *     result_type value_ = 0;
618    *     int n_ = 0;
619    *     for (; first != last; ++first, ++n_)
620    *       value_ += *first;
621    *     return value_ / n_;
622    *   }
623    * };
624    * @endcode
625    *
626    * @par Example 2:
627    * This accumulator stops signal emission when a slot returns zero:
628    * @code
629    * struct interruptable_accumulator
630    * {
631    *   typedef bool result_type;
632    *   template<typename T_iterator>
633    *   result_type operator()(T_iterator first, T_iterator last) const
634    *   {
635    *     for (; first != last; ++first, ++n_)
636    *       if (!*first) return false;
637    *     return true;
638    *   }
639    * };
640    * @endcode
641    *
642    * @ingroup signal
643 ],[
644   /** Convenience wrapper for the numbered sigc::signal$1 template.
645    * Like sigc::signal but the additional template parameter @e T_accumulator
646    * defines the accumulator type that should be used.
647 ])dnl
648    */
649   template <class T_accumulator>
650   class accumulated
651     : public signal$1<LIST(T_return, LOOP(T_arg%1, $1), T_accumulator)>
652   {
653   public:
654     accumulated() {}
655     accumulated(const accumulated& src)
656       : signal$1<LIST(T_return, LOOP(T_arg%1, $1), T_accumulator)>(src) {}
657   };
658
659   signal() {}
660
661   signal(const signal& src)
662     : signal$1<LIST(T_return, LOOP(T_arg%1, $1),nil)>(src) {}
663
664   signal(signal&& src)
665     : signal$1<LIST(T_return, LOOP(T_arg%1, $1),nil)>(std::move(src)) {}
666
667   signal& operator=(const signal& src)
668   {
669     signal$1<LIST(T_return, LOOP(T_arg%1, $1),nil)>::operator=(src);
670     return *this;
671   }
672
673   signal& operator=(signal&& src)
674   {
675     signal$1<LIST(T_return, LOOP(T_arg%1, $1),nil)>::operator=(std::move(src));
676     return *this;
677   }
678 };
679
680
681 ])
682
683 divert(0)
684 #ifndef _SIGC_SIGNAL_H_
685 #define _SIGC_SIGNAL_H_
686
687 #include <list>
688 #include <sigc++/signal_base.h>
689 #include <sigc++/type_traits.h>
690 #include <sigc++/trackable.h>
691 #include <sigc++/functors/slot.h>
692 #include <sigc++/functors/mem_fun.h>
693
694 //TODO: See comment in functor_trait.h.
695 #if defined(nil) && defined(SIGC_PRAGMA_PUSH_POP_MACRO)
696   #define SIGC_NIL_HAS_BEEN_PUSHED 1
697   #pragma push_macro("nil")
698   #undef nil
699 #endif
700
701 //SIGC_TYPEDEF_REDEFINE_ALLOWED:
702 // TODO: This should have its own test, but I can not create one that gives the error instead of just a warning. murrayc.
703 // I have just used this because there is a correlation between these two problems.
704 #ifdef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD
705   //Compilers, such as older versions of SUN Forte C++, that do not allow this also often
706   //do not allow a typedef to have the same name as a class in the typedef's definition.
707   //For Sun Forte CC 5.7 (SUN Workshop 10), comment this out to fix the build.
708   #define SIGC_TYPEDEF_REDEFINE_ALLOWED 1
709 #endif
710
711 namespace sigc {
712
713 /** STL-style iterator for slot_list.
714  *
715  * @ingroup signal
716  */
717 template <typename T_slot>
718 struct slot_iterator
719 {
720   typedef std::size_t                     size_type;
721   typedef std::ptrdiff_t                  difference_type;
722   typedef std::bidirectional_iterator_tag iterator_category;
723
724   typedef T_slot  slot_type;
725
726   typedef T_slot  value_type;
727   typedef T_slot* pointer;
728   typedef T_slot& reference;
729
730   typedef typename internal::signal_impl::iterator_type iterator_type;
731
732   slot_iterator()
733     {}
734
735   explicit slot_iterator(const iterator_type& i)
736     : i_(i) {}
737
738   reference operator*() const
739     { return static_cast<reference>(*i_); }
740
741   pointer operator->() const
742     { return &(operator*()); }
743
744   slot_iterator& operator++()
745     {
746       ++i_;
747       return *this;
748     }
749
750   slot_iterator operator++(int)
751     { 
752       slot_iterator __tmp(*this);
753       ++i_;
754       return __tmp;
755     }
756
757   slot_iterator& operator--()
758     {
759       --i_;
760       return *this;
761     }
762
763   slot_iterator operator--(int)
764     {
765       slot_iterator __tmp(*this);
766       --i_;
767       return __tmp;
768     }
769
770   bool operator == (const slot_iterator& other) const
771     { return i_ == other.i_; }
772
773   bool operator != (const slot_iterator& other) const
774     { return i_ != other.i_; }
775
776   iterator_type i_;
777 };
778
779 /** STL-style const iterator for slot_list.
780  *
781  * @ingroup signal
782  */
783 template <typename T_slot>
784 struct slot_const_iterator
785 {
786   typedef std::size_t                     size_type;
787   typedef std::ptrdiff_t                  difference_type;
788   typedef std::bidirectional_iterator_tag iterator_category;
789
790   typedef T_slot        slot_type;
791
792   typedef T_slot        value_type;
793   typedef const T_slot* pointer;
794   typedef const T_slot& reference;
795
796   typedef typename internal::signal_impl::const_iterator_type iterator_type;
797
798   slot_const_iterator()
799     {}
800
801   explicit slot_const_iterator(const iterator_type& i)
802     : i_(i) {}
803
804   reference operator*() const
805     { return static_cast<reference>(*i_); }
806
807   pointer operator->() const
808     { return &(operator*()); }
809
810   slot_const_iterator& operator++()
811     {
812       ++i_;
813       return *this;
814     }
815
816   slot_const_iterator operator++(int)
817     { 
818       slot_const_iterator __tmp(*this);
819       ++i_;
820       return __tmp;
821     }
822
823   slot_const_iterator& operator--()
824     {
825       --i_;
826       return *this;
827     }
828
829   slot_const_iterator operator--(int)
830     {
831       slot_const_iterator __tmp(*this);
832       --i_;
833       return __tmp;
834     }
835
836   bool operator == (const slot_const_iterator& other) const
837     { return i_ == other.i_; }
838
839   bool operator != (const slot_const_iterator& other) const
840     { return i_ != other.i_; }
841
842   iterator_type i_;
843 };
844
845 /** STL-style list interface for sigc::signal#.
846  * slot_list can be used to iterate over the list of slots that
847  * is managed by a signal. Slots can be added or removed from
848  * the list while existing iterators stay valid.
849  *
850  * @ingroup signal
851  */
852 template <class T_slot>
853 struct slot_list
854 {
855   typedef T_slot slot_type;
856
857   typedef slot_type&       reference;
858   typedef const slot_type& const_reference;
859
860   typedef slot_iterator<slot_type>              iterator;
861   typedef slot_const_iterator<slot_type>        const_iterator;
862   
863   #ifndef SIGC_HAVE_SUN_REVERSE_ITERATOR
864   typedef std::reverse_iterator<iterator>       reverse_iterator;
865   typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
866   #else
867   typedef std::reverse_iterator<iterator, std::random_access_iterator_tag,
868                                 int, int&, int*, std::ptrdiff_t> reverse_iterator;
869
870   typedef std::reverse_iterator<const_iterator, std::random_access_iterator_tag,
871                                 int, const int&, const int*, std::ptrdiff_t> const_reverse_iterator;
872   #endif /* SIGC_HAVE_SUN_REVERSE_ITERATOR */
873
874
875   slot_list()
876     : list_(nullptr) {}
877
878   explicit slot_list(internal::signal_impl* __list)
879     : list_(__list) {}
880
881   iterator begin()
882     { return iterator(list_->slots_.begin()); }
883
884   const_iterator begin() const
885     { return const_iterator(list_->slots_.begin()); }
886
887   iterator end()
888     { return iterator(list_->slots_.end()); }
889
890   const_iterator end() const
891     { return const_iterator(list_->slots_.end()); }
892
893   reverse_iterator rbegin() 
894     { return reverse_iterator(end()); }
895
896   const_reverse_iterator rbegin() const 
897     { return const_reverse_iterator(end()); }
898
899   reverse_iterator rend()
900     { return reverse_iterator(begin()); }
901
902   const_reverse_iterator rend() const
903     { return const_reverse_iterator(begin()); }
904
905   reference front()
906     { return *begin(); }
907
908   const_reference front() const
909     { return *begin(); }
910
911   reference back()
912     { return *(--end()); }
913
914   const_reference back() const
915     { return *(--end()); }
916
917   iterator insert(iterator i, const slot_type& slot_)
918     { return iterator(list_->insert(i.i_, static_cast<const slot_base&>(slot_))); }
919
920   iterator insert(iterator i, slot_type&& slot_)
921     { return iterator(list_->insert(i.i_, std::move(static_cast<slot_base&>(slot_)))); }
922
923   void push_front(const slot_type& c)
924     { insert(begin(), c); }
925
926   void push_front(slot_type&& c)
927     { insert(begin(), std::move(c)); }
928
929   void push_back(const slot_type& c)
930     { insert(end(), c); }
931
932   void push_back(slot_type&& c)
933     { insert(end(), std::move(c)); }
934
935   iterator erase(iterator i)
936     { return iterator(list_->erase(i.i_)); }
937
938   iterator erase(iterator first_, iterator last_)
939     {
940       while (first_ != last_)
941         first_ = erase(first_);
942       return last_;
943     }
944
945   void pop_front()
946     { erase(begin()); }
947
948   void pop_back()
949     { 
950       auto tmp_ = end();
951       erase(--tmp_);
952     }
953
954 protected:
955   internal::signal_impl* list_;
956 };
957
958
959 namespace internal {
960
961 /** Special iterator over sigc::internal::signal_impl's slot list that holds extra data.
962  * This iterators is for use in accumulators. operator*() executes
963  * the slot. The return value is buffered, so that in an expression
964  * like @code a = (*i) * (*i); @endcode the slot is executed only once.
965  */
966 template <class T_emitter, class T_result = typename T_emitter::result_type>
967 struct slot_iterator_buf
968 {
969   typedef std::size_t                      size_type;
970   typedef std::ptrdiff_t                   difference_type;
971   typedef std::bidirectional_iterator_tag  iterator_category;
972
973   //These are needed just to make this a proper C++ iterator, 
974   //that can be used with standard C++ algorithms.
975   typedef T_result                         value_type;
976   typedef T_result&                        reference;
977   typedef T_result*                        pointer;
978
979   typedef T_emitter                        emitter_type;
980   typedef T_result                         result_type;
981   typedef typename T_emitter::slot_type    slot_type;
982
983   typedef signal_impl::const_iterator_type iterator_type;
984
985   slot_iterator_buf()
986     : c_(nullptr), invoked_(false) {}
987
988   slot_iterator_buf(const iterator_type& i, const emitter_type* c)
989     : i_(i), c_(c), invoked_(false) {}
990
991   result_type operator*() const
992     {
993       if (!i_->empty() && !i_->blocked() && !invoked_)
994         {
995           r_ = (*c_)(static_cast<const slot_type&>(*i_));
996           invoked_ = true;
997         }
998       return r_;
999     }
1000
1001   slot_iterator_buf& operator++()
1002     {
1003       ++i_;
1004       invoked_ = false;
1005       return *this;
1006     }
1007
1008   slot_iterator_buf operator++(int)
1009     { 
1010       slot_iterator_buf __tmp(*this);
1011       ++i_;
1012       invoked_ = false;
1013       return __tmp;
1014     }
1015
1016   slot_iterator_buf& operator--()
1017     {
1018       --i_;
1019       invoked_ = false;
1020       return *this;
1021     }
1022
1023   slot_iterator_buf operator--(int)
1024     {
1025       slot_iterator_buf __tmp(*this);
1026       --i_;
1027       invoked_ = false;
1028       return __tmp;
1029     }
1030
1031   bool operator == (const slot_iterator_buf& other) const
1032     { return (!c_ || (i_ == other.i_)); } /* If '!c_' the iterators are empty.
1033                                            * Unfortunately, empty stl iterators are not equal.
1034                                            * We are forcing equality so that 'first==last'
1035                                            * in the accumulator's emit function yields true. */
1036
1037   bool operator != (const slot_iterator_buf& other) const
1038     { return (c_ && (i_ != other.i_)); }
1039
1040 private:
1041   iterator_type i_;
1042   const emitter_type* c_;
1043   mutable result_type r_;
1044   mutable bool invoked_;
1045 };
1046
1047 /** Template specialization of slot_iterator_buf for void return signals.
1048  */
1049 template <class T_emitter>
1050 struct slot_iterator_buf<T_emitter, void>
1051 {
1052   typedef std::size_t                      size_type;
1053   typedef std::ptrdiff_t                   difference_type;
1054   typedef std::bidirectional_iterator_tag  iterator_category;
1055
1056   typedef T_emitter                        emitter_type;
1057   typedef void                             result_type;
1058   typedef typename T_emitter::slot_type    slot_type;
1059
1060   typedef signal_impl::const_iterator_type iterator_type;
1061
1062   slot_iterator_buf()
1063     : c_(nullptr), invoked_(false) {}
1064
1065   slot_iterator_buf(const iterator_type& i, const emitter_type* c)
1066     : i_(i), c_(c), invoked_(false) {}
1067
1068   void operator*() const
1069     {
1070       if (!i_->empty() && !i_->blocked() && !invoked_)
1071         {
1072           (*c_)(static_cast<const slot_type&>(*i_));
1073           invoked_ = true;
1074         }
1075     }
1076
1077   slot_iterator_buf& operator++()
1078     {
1079       ++i_;
1080       invoked_ = false;
1081       return *this;
1082     }
1083
1084   slot_iterator_buf operator++(int)
1085     { 
1086       slot_iterator_buf __tmp(*this);
1087       ++i_;
1088       invoked_ = false;
1089       return __tmp;
1090     }
1091
1092   slot_iterator_buf& operator--()
1093     {
1094       --i_;
1095       invoked_ = false;
1096       return *this;
1097     }
1098
1099   slot_iterator_buf operator--(int)
1100     {
1101       slot_iterator_buf __tmp(*this);
1102       --i_;
1103       invoked_ = false;
1104       return __tmp;
1105     }
1106
1107   bool operator == (const slot_iterator_buf& other) const
1108     { return i_ == other.i_; }
1109
1110   bool operator != (const slot_iterator_buf& other) const
1111     { return i_ != other.i_; }
1112
1113 private:
1114   iterator_type i_;
1115   const emitter_type* c_;
1116   mutable bool invoked_;
1117 };
1118
1119 /** Reverse version of sigc::internal::slot_iterator_buf. */
1120 template <class T_emitter, class T_result = typename T_emitter::result_type>
1121 struct slot_reverse_iterator_buf
1122 {
1123   typedef std::size_t                      size_type;
1124   typedef std::ptrdiff_t                   difference_type;
1125   typedef std::bidirectional_iterator_tag  iterator_category;
1126
1127   //These are needed just to make this a proper C++ iterator, 
1128   //that can be used with standard C++ algorithms.
1129   typedef T_result                         value_type;
1130   typedef T_result&                        reference;
1131   typedef T_result*                        pointer;
1132
1133   typedef T_emitter                        emitter_type;
1134   typedef T_result                         result_type;
1135   typedef typename T_emitter::slot_type    slot_type;
1136
1137   typedef signal_impl::const_iterator_type iterator_type;
1138
1139   slot_reverse_iterator_buf()
1140     : c_(nullptr), invoked_(false) {}
1141
1142   slot_reverse_iterator_buf(const iterator_type& i, const emitter_type* c)
1143     : i_(i), c_(c), invoked_(false) {}
1144
1145   result_type operator*() const
1146     {
1147       auto __tmp(i_);
1148           --__tmp;
1149       if (!__tmp->empty() && !__tmp->blocked() && !invoked_)
1150         {
1151           r_ = (*c_)(static_cast<const slot_type&>(*__tmp));
1152           invoked_ = true;
1153         }
1154       return r_;
1155     }
1156
1157   slot_reverse_iterator_buf& operator++()
1158     {
1159       --i_;
1160       invoked_ = false;
1161       return *this;
1162     }
1163
1164   slot_reverse_iterator_buf operator++(int)
1165     { 
1166       slot_reverse_iterator_buf __tmp(*this);
1167       --i_;
1168       invoked_ = false;
1169       return __tmp;
1170     }
1171
1172   slot_reverse_iterator_buf& operator--()
1173     {
1174       ++i_;
1175       invoked_ = false;
1176       return *this;
1177     }
1178
1179   slot_reverse_iterator_buf operator--(int)
1180     {
1181       slot_reverse_iterator_buf __tmp(*this);
1182       ++i_;
1183       invoked_ = false;
1184       return __tmp;
1185     }
1186
1187   bool operator == (const slot_reverse_iterator_buf& other) const
1188     { return (!c_ || (i_ == other.i_)); } /* If '!c_' the iterators are empty.
1189                                            * Unfortunately, empty stl iterators are not equal.
1190                                            * We are forcing equality so that 'first==last'
1191                                            * in the accumulator's emit function yields true. */
1192
1193   bool operator != (const slot_reverse_iterator_buf& other) const
1194     { return (c_ && (i_ != other.i_)); }
1195
1196 private:
1197   iterator_type i_;
1198   const emitter_type* c_;
1199   mutable result_type r_;
1200   mutable bool invoked_;
1201 };
1202
1203 /** Template specialization of slot_reverse_iterator_buf for void return signals.
1204  */
1205 template <class T_emitter>
1206 struct slot_reverse_iterator_buf<T_emitter, void>
1207 {
1208   typedef std::size_t                      size_type;
1209   typedef std::ptrdiff_t                   difference_type;
1210   typedef std::bidirectional_iterator_tag  iterator_category;
1211
1212   typedef T_emitter                        emitter_type;
1213   typedef void                             result_type;
1214   typedef typename T_emitter::slot_type    slot_type;
1215
1216   typedef signal_impl::const_iterator_type iterator_type;
1217
1218   slot_reverse_iterator_buf()
1219     : c_(nullptr), invoked_(false) {}
1220
1221   slot_reverse_iterator_buf(const iterator_type& i, const emitter_type* c)
1222     : i_(i), c_(c), invoked_(false) {}
1223
1224   void operator*() const
1225     {
1226       auto __tmp(i_);
1227           --__tmp;
1228           if (!__tmp->empty() && !__tmp->blocked() && !invoked_)
1229         {
1230           (*c_)(static_cast<const slot_type&>(*__tmp));
1231           invoked_ = true;
1232         }
1233     }
1234
1235   slot_reverse_iterator_buf& operator++()
1236     {
1237       --i_;
1238       invoked_ = false;
1239       return *this;
1240     }
1241
1242   slot_reverse_iterator_buf operator++(int)
1243     { 
1244       slot_reverse_iterator_buf __tmp(*this);
1245       --i_;
1246       invoked_ = false;
1247       return __tmp;
1248     }
1249
1250   slot_reverse_iterator_buf& operator--()
1251     {
1252       ++i_;
1253       invoked_ = false;
1254       return *this;
1255     }
1256
1257   slot_reverse_iterator_buf operator--(int)
1258     {
1259       slot_reverse_iterator_buf __tmp(*this);
1260       ++i_;
1261       invoked_ = false;
1262       return __tmp;
1263     }
1264
1265   bool operator == (const slot_reverse_iterator_buf& other) const
1266     { return i_ == other.i_; }
1267
1268   bool operator != (const slot_reverse_iterator_buf& other) const
1269     { return i_ != other.i_; }
1270
1271 private:
1272   iterator_type i_;
1273   const emitter_type* c_;
1274   mutable bool invoked_;
1275 };
1276
1277 FOR(0,CALL_SIZE,[[SIGNAL_EMIT_N(%1)]])
1278 } /* namespace internal */
1279
1280 FOR(0,CALL_SIZE,[[SIGNAL_N(%1)]])
1281
1282 SIGNAL(CALL_SIZE,CALL_SIZE)
1283 FOR(0,eval(CALL_SIZE-1),[[SIGNAL(%1)]])
1284
1285 } /* namespace sigc */
1286
1287 #ifdef SIGC_NIL_HAS_BEEN_PUSHED
1288   #undef SIGC_NIL_HAS_BEEN_PUSHED
1289   #pragma pop_macro("nil")
1290 #endif
1291
1292 #endif /* _SIGC_SIGNAL_H_ */