Imported Upstream version 2.99.2
[platform/upstream/libsigc++.git] / sigc++ / signal.h
1 /*
2  * Copyright 2002-2016, The libsigc++ Development Team
3  *
4  *  This library is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU Lesser General Public
6  *  License as published by the Free Software Foundation; either
7  *  version 2.1 of the License, or (at your option) any later version.
8  *
9  *  This library is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  *  Lesser General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Lesser General Public
15  *  License along with this library; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  */
19
20 #ifndef _SIGC_SIGNAL_H_
21 #define _SIGC_SIGNAL_H_
22
23 #include <list>
24 #include <sigc++/signal_base.h>
25 #include <sigc++/type_traits.h>
26 #include <sigc++/trackable.h>
27 #include <sigc++/functors/slot.h>
28 #include <sigc++/functors/mem_fun.h>
29 #include <tuple>
30 #include <utility>
31
32 namespace sigc {
33
34 /** STL-style iterator for slot_list.
35  *
36  * @ingroup signal
37  */
38 template <typename T_slot>
39 struct slot_iterator
40 {
41   using size_type = std::size_t;
42   using difference_type = std::ptrdiff_t;
43   using iterator_category = std::bidirectional_iterator_tag;
44
45   using slot_type = T_slot;
46
47   using value_type = T_slot;
48   using pointer = T_slot*;
49   using reference = T_slot&;
50
51   using iterator_type = typename internal::signal_impl::iterator_type;
52
53   slot_iterator()
54     {}
55
56   explicit slot_iterator(const iterator_type& i)
57     : i_(i) {}
58
59   reference operator*() const
60     { return static_cast<reference>(*i_); }
61
62   pointer operator->() const
63     { return &(operator*()); }
64
65   slot_iterator& operator++()
66     {
67       ++i_;
68       return *this;
69     }
70
71   slot_iterator operator++(int)
72     { 
73       slot_iterator __tmp(*this);
74       ++i_;
75       return __tmp;
76     }
77
78   slot_iterator& operator--()
79     {
80       --i_;
81       return *this;
82     }
83
84   slot_iterator operator--(int)
85     {
86       slot_iterator __tmp(*this);
87       --i_;
88       return __tmp;
89     }
90
91   bool operator == (const slot_iterator& other) const
92     { return i_ == other.i_; }
93
94   bool operator != (const slot_iterator& other) const
95     { return i_ != other.i_; }
96
97   iterator_type i_;
98 };
99
100 /** STL-style const iterator for slot_list.
101  *
102  * @ingroup signal
103  */
104 template <typename T_slot>
105 struct slot_const_iterator
106 {
107   using size_type = std::size_t;
108   using difference_type = std::ptrdiff_t;
109   using iterator_category = std::bidirectional_iterator_tag;
110
111   using slot_type = T_slot;
112
113   using value_type = T_slot;
114   using pointer = const T_slot*;
115   using reference = const T_slot&;
116
117   using iterator_type = typename internal::signal_impl::const_iterator_type;
118
119   slot_const_iterator()
120     {}
121
122   explicit slot_const_iterator(const iterator_type& i)
123     : i_(i) {}
124
125   reference operator*() const
126     { return static_cast<reference>(*i_); }
127
128   pointer operator->() const
129     { return &(operator*()); }
130
131   slot_const_iterator& operator++()
132     {
133       ++i_;
134       return *this;
135     }
136
137   slot_const_iterator operator++(int)
138     { 
139       slot_const_iterator __tmp(*this);
140       ++i_;
141       return __tmp;
142     }
143
144   slot_const_iterator& operator--()
145     {
146       --i_;
147       return *this;
148     }
149
150   slot_const_iterator operator--(int)
151     {
152       slot_const_iterator __tmp(*this);
153       --i_;
154       return __tmp;
155     }
156
157   bool operator == (const slot_const_iterator& other) const
158     { return i_ == other.i_; }
159
160   bool operator != (const slot_const_iterator& other) const
161     { return i_ != other.i_; }
162
163   iterator_type i_;
164 };
165
166 /** STL-style list interface for sigc::signal#.
167  * slot_list can be used to iterate over the list of slots that
168  * is managed by a signal. Slots can be added or removed from
169  * the list while existing iterators stay valid. A slot_list
170  * object can be retrieved from the signal's slots() function.
171  *
172  * @ingroup signal
173  */
174 template <class T_slot>
175 struct slot_list
176 {
177   using slot_type = T_slot;
178
179   using reference = slot_type&;
180   using const_reference = const slot_type&;
181
182   using iterator = slot_iterator<slot_type>;
183   using const_iterator = slot_const_iterator<slot_type>;
184   
185   using reverse_iterator = std::reverse_iterator<iterator>;
186   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
187
188   slot_list()
189     : list_(nullptr) {}
190
191   explicit slot_list(internal::signal_impl* __list)
192     : list_(__list) {}
193
194   iterator begin()
195     { return iterator(list_->slots_.begin()); }
196
197   const_iterator begin() const
198     { return const_iterator(list_->slots_.begin()); }
199
200   iterator end()
201     { return iterator(list_->slots_.end()); }
202
203   const_iterator end() const
204     { return const_iterator(list_->slots_.end()); }
205
206   reverse_iterator rbegin() 
207     { return reverse_iterator(end()); }
208
209   const_reverse_iterator rbegin() const 
210     { return const_reverse_iterator(end()); }
211
212   reverse_iterator rend()
213     { return reverse_iterator(begin()); }
214
215   const_reverse_iterator rend() const
216     { return const_reverse_iterator(begin()); }
217
218   reference front()
219     { return *begin(); }
220
221   const_reference front() const
222     { return *begin(); }
223
224   reference back()
225     { return *(--end()); }
226
227   const_reference back() const
228     { return *(--end()); }
229
230   iterator insert(iterator i, const slot_type& slot_)
231     { return iterator(list_->insert(i.i_, static_cast<const slot_base&>(slot_))); }
232
233   iterator insert(iterator i, slot_type&& slot_)
234     { return iterator(list_->insert(i.i_, std::move(static_cast<slot_base&>(slot_)))); }
235
236   void push_front(const slot_type& c)
237     { insert(begin(), c); }
238
239   void push_front(slot_type&& c)
240     { insert(begin(), std::move(c)); }
241
242   void push_back(const slot_type& c)
243     { insert(end(), c); }
244
245   void push_back(slot_type&& c)
246     { insert(end(), std::move(c)); }
247
248   iterator erase(iterator i)
249     { return iterator(list_->erase(i.i_)); }
250
251   iterator erase(iterator first_, iterator last_)
252     {
253       while (first_ != last_)
254         first_ = erase(first_);
255       return last_;
256     }
257
258   void pop_front()
259     { erase(begin()); }
260
261   void pop_back()
262     { 
263       auto tmp_ = end();
264       erase(--tmp_);
265     }
266
267 protected:
268   internal::signal_impl* list_;
269 };
270
271
272 namespace internal {
273
274 /** Special iterator over sigc::internal::signal_impl's slot list that holds extra data.
275  * This iterators is for use in accumulators. operator*() executes
276  * the slot. The return value is buffered, so that in an expression
277  * like @code a = (*i) * (*i); @endcode the slot is executed only once.
278  */
279 template <class T_emitter, class T_result = typename T_emitter::result_type>
280 struct slot_iterator_buf
281 {
282   using size_type = std::size_t;
283   using difference_type = std::ptrdiff_t;
284   using iterator_category = std::bidirectional_iterator_tag;
285
286   //These are needed just to make this a proper C++ iterator, 
287   //that can be used with standard C++ algorithms.
288   using value_type = T_result;
289   using reference = T_result&;
290   using pointer = T_result*;
291
292   using emitter_type = T_emitter;
293   using result_type = T_result;
294   using slot_type = typename T_emitter::slot_type;
295
296   using iterator_type = signal_impl::const_iterator_type;
297
298   slot_iterator_buf()
299     : c_(nullptr), invoked_(false) {}
300
301   slot_iterator_buf(const iterator_type& i, const emitter_type* c)
302     : i_(i), c_(c), invoked_(false) {}
303
304   decltype(auto) operator*() const
305     {
306       if (!i_->empty() && !i_->blocked() && !invoked_)
307         {
308           r_ = (*c_)(static_cast<const slot_type&>(*i_));
309           invoked_ = true;
310         }
311       return r_;
312     }
313
314   slot_iterator_buf& operator++()
315     {
316       ++i_;
317       invoked_ = false;
318       return *this;
319     }
320
321   slot_iterator_buf operator++(int)
322     { 
323       slot_iterator_buf __tmp(*this);
324       ++i_;
325       invoked_ = false;
326       return __tmp;
327     }
328
329   slot_iterator_buf& operator--()
330     {
331       --i_;
332       invoked_ = false;
333       return *this;
334     }
335
336   slot_iterator_buf operator--(int)
337     {
338       slot_iterator_buf __tmp(*this);
339       --i_;
340       invoked_ = false;
341       return __tmp;
342     }
343
344   bool operator == (const slot_iterator_buf& other) const
345     { return (!c_ || (i_ == other.i_)); } /* If '!c_' the iterators are empty.
346                                            * Unfortunately, empty stl iterators are not equal.
347                                            * We are forcing equality so that 'first==last'
348                                            * in the accumulator's emit function yields true. */
349
350   bool operator != (const slot_iterator_buf& other) const
351     { return (c_ && (i_ != other.i_)); }
352
353 private:
354   iterator_type i_;
355   const emitter_type* c_;
356   mutable result_type r_;
357   mutable bool invoked_;
358 };
359
360 /** Template specialization of slot_iterator_buf for void return signals.
361  */
362 template <class T_emitter>
363 struct slot_iterator_buf<T_emitter, void>
364 {
365   using size_type = std::size_t;
366   using difference_type = std::ptrdiff_t;
367   using iterator_category = std::bidirectional_iterator_tag;
368
369   using emitter_type = T_emitter;
370   using result_type = void;
371   using slot_type = typename T_emitter::slot_type;
372
373   using iterator_type = signal_impl::const_iterator_type;
374
375   slot_iterator_buf()
376     : c_(nullptr), invoked_(false) {}
377
378   slot_iterator_buf(const iterator_type& i, const emitter_type* c)
379     : i_(i), c_(c), invoked_(false) {}
380
381   void operator*() const
382     {
383       if (!i_->empty() && !i_->blocked() && !invoked_)
384         {
385           (*c_)(static_cast<const slot_type&>(*i_));
386           invoked_ = true;
387         }
388     }
389
390   slot_iterator_buf& operator++()
391     {
392       ++i_;
393       invoked_ = false;
394       return *this;
395     }
396
397   slot_iterator_buf operator++(int)
398     { 
399       slot_iterator_buf __tmp(*this);
400       ++i_;
401       invoked_ = false;
402       return __tmp;
403     }
404
405   slot_iterator_buf& operator--()
406     {
407       --i_;
408       invoked_ = false;
409       return *this;
410     }
411
412   slot_iterator_buf operator--(int)
413     {
414       slot_iterator_buf __tmp(*this);
415       --i_;
416       invoked_ = false;
417       return __tmp;
418     }
419
420   bool operator == (const slot_iterator_buf& other) const
421     { return i_ == other.i_; }
422
423   bool operator != (const slot_iterator_buf& other) const
424     { return i_ != other.i_; }
425
426 private:
427   iterator_type i_;
428   const emitter_type* c_;
429   mutable bool invoked_;
430 };
431
432 /** Reverse version of sigc::internal::slot_iterator_buf. */
433 template <class T_emitter, class T_result = typename T_emitter::result_type>
434 struct slot_reverse_iterator_buf
435 {
436   using size_type = std::size_t;
437   using difference_type = std::ptrdiff_t;
438   using iterator_category = std::bidirectional_iterator_tag;
439
440   //These are needed just to make this a proper C++ iterator, 
441   //that can be used with standard C++ algorithms.
442   using value_type = T_result;
443   using reference = T_result&;
444   using pointer = T_result*;
445
446   using emitter_type = T_emitter;
447   using result_type = T_result;
448   using slot_type = typename T_emitter::slot_type;
449
450   using iterator_type = signal_impl::const_iterator_type;
451
452   slot_reverse_iterator_buf()
453     : c_(nullptr), invoked_(false) {}
454
455   slot_reverse_iterator_buf(const iterator_type& i, const emitter_type* c)
456     : i_(i), c_(c), invoked_(false) {}
457
458   decltype(auto) operator*() const
459     {
460       iterator_type __tmp(i_);
461           --__tmp;
462       if (!__tmp->empty() && !__tmp->blocked() && !invoked_)
463         {
464           r_ = (*c_)(static_cast<const slot_type&>(*__tmp));
465           invoked_ = true;
466         }
467       return r_;
468     }
469
470   slot_reverse_iterator_buf& operator++()
471     {
472       --i_;
473       invoked_ = false;
474       return *this;
475     }
476
477   slot_reverse_iterator_buf operator++(int)
478     { 
479       slot_reverse_iterator_buf __tmp(*this);
480       --i_;
481       invoked_ = false;
482       return __tmp;
483     }
484
485   slot_reverse_iterator_buf& operator--()
486     {
487       ++i_;
488       invoked_ = false;
489       return *this;
490     }
491
492   slot_reverse_iterator_buf operator--(int)
493     {
494       slot_reverse_iterator_buf __tmp(*this);
495       ++i_;
496       invoked_ = false;
497       return __tmp;
498     }
499
500   bool operator == (const slot_reverse_iterator_buf& other) const
501     { return (!c_ || (i_ == other.i_)); } /* If '!c_' the iterators are empty.
502                                            * Unfortunately, empty stl iterators are not equal.
503                                            * We are forcing equality so that 'first==last'
504                                            * in the accumulator's emit function yields true. */
505
506   bool operator != (const slot_reverse_iterator_buf& other) const
507     { return (c_ && (i_ != other.i_)); }
508
509 private:
510   iterator_type i_;
511   const emitter_type* c_;
512   mutable result_type r_;
513   mutable bool invoked_;
514 };
515
516 /** Template specialization of slot_reverse_iterator_buf for void return signals.
517  */
518 template <class T_emitter>
519 struct slot_reverse_iterator_buf<T_emitter, void>
520 {
521   using size_type = std::size_t;
522   using difference_type = std::ptrdiff_t;
523   using iterator_category = std::bidirectional_iterator_tag;
524
525   using emitter_type = T_emitter;
526   using result_type = void;
527   using slot_type = typename T_emitter::slot_type;
528
529   using iterator_type = signal_impl::const_iterator_type;
530
531   slot_reverse_iterator_buf()
532     : c_(nullptr), invoked_(false) {}
533
534   slot_reverse_iterator_buf(const iterator_type& i, const emitter_type* c)
535     : i_(i), c_(c), invoked_(false) {}
536
537   void operator*() const
538     {
539       iterator_type __tmp(i_);
540           --__tmp;
541           if (!__tmp->empty() && !__tmp->blocked() && !invoked_)
542         {
543           (*c_)(static_cast<const slot_type&>(*__tmp));
544           invoked_ = true;
545         }
546     }
547
548   slot_reverse_iterator_buf& operator++()
549     {
550       --i_;
551       invoked_ = false;
552       return *this;
553     }
554
555   slot_reverse_iterator_buf operator++(int)
556     { 
557       slot_reverse_iterator_buf __tmp(*this);
558       --i_;
559       invoked_ = false;
560       return __tmp;
561     }
562
563   slot_reverse_iterator_buf& operator--()
564     {
565       ++i_;
566       invoked_ = false;
567       return *this;
568     }
569
570   slot_reverse_iterator_buf operator--(int)
571     {
572       slot_reverse_iterator_buf __tmp(*this);
573       ++i_;
574       invoked_ = false;
575       return __tmp;
576     }
577
578   bool operator == (const slot_reverse_iterator_buf& other) const
579     { return i_ == other.i_; }
580
581   bool operator != (const slot_reverse_iterator_buf& other) const
582     { return i_ != other.i_; }
583
584 private:
585   iterator_type i_;
586   const emitter_type* c_;
587   mutable bool invoked_;
588 };
589
590
591 /** Abstracts signal emission.
592  * This template implements the emit() function of signal_with_accumulator.
593  * Template specializations are available to optimize signal
594  * emission when no accumulator is used, for example when the template
595  * argument @e T_accumulator is @p void.
596  */
597 template <class T_return, class T_accumulator, class... T_arg>
598 struct signal_emit
599 {
600   using self_type = signal_emit<T_return, T_accumulator, T_arg...>;
601   using result_type = typename T_accumulator::result_type;
602   using slot_type = slot<T_return(T_arg...)>;
603   using slot_iterator_buf_type = internal::slot_iterator_buf<self_type, T_return>;
604   using slot_reverse_iterator_buf_type = internal::slot_reverse_iterator_buf<self_type, T_return>;
605   using iterator_type = signal_impl::const_iterator_type;
606
607   /** Instantiates the class.
608    * The parameters are stored in member variables. operator()() passes
609    * the values on to some slot.
610    */
611   signal_emit(type_trait_take_t<T_arg>... _A_a)
612     : _A_a_(_A_a...) {}
613
614   /** Invokes a slot using the buffered parameter values.
615    * @param _A_slot Some slot to invoke.
616    * @return The slot's return value.
617    */
618   T_return operator()(const slot_type& _A_slot) const
619     {
620       const auto seq = std::make_index_sequence<std::tuple_size<decltype(_A_a_)>::value>();
621       return call_call_type_operator_parentheses_with_tuple(_A_slot, _A_a_, seq);
622     }
623
624   /** Executes a list of slots using an accumulator of type @e T_accumulator.
625    * The arguments are buffered in a temporary instance of signal_emit.
626    * @param _A_a Arguments to be passed on to the slots.
627    * @return The accumulated return values of the slot invocations as processed by the accumulator.
628    */
629   static decltype(auto) emit(signal_impl* impl, type_trait_take_t<T_arg>... _A_a)
630     {
631       T_accumulator accumulator;
632
633       if (!impl)
634         return accumulator(slot_iterator_buf_type(), slot_iterator_buf_type());
635
636       signal_exec exec(impl);
637       temp_slot_list slots(impl->slots_);
638
639       self_type self(_A_a...);
640       return accumulator(slot_iterator_buf_type(slots.begin(), &self),
641                          slot_iterator_buf_type(slots.end(), &self));
642     }
643
644   /** Executes a list of slots using an accumulator of type @e T_accumulator in reverse order.   * The arguments are buffered in a temporary instance of signal_emit.
645    * @param _A_a Arguments to be passed on to the slots.
646    * @return The accumulated return values of the slot invocations as processed by the accumulator.
647    */
648   static decltype(auto) emit_reverse(signal_impl* impl, type_trait_take_t<T_arg>... _A_a)
649     {
650       T_accumulator accumulator;
651
652       if (!impl)
653         return accumulator(slot_iterator_buf_type(), slot_iterator_buf_type());
654
655       signal_exec exec(impl);
656       temp_slot_list slots(impl->slots_);
657
658       self_type self(_A_a...);
659       return accumulator(slot_reverse_iterator_buf_type(slots.end(), &self),
660                          slot_reverse_iterator_buf_type(slots.begin(), &self));
661     }
662
663   std::tuple<type_trait_take_t<T_arg>...> _A_a_;
664
665 private:
666   //TODO_variadic: Replace this with std::experimental::apply() if that becomes standard
667   //C++, or add our own implementation, to avoid code duplication.
668   template<std::size_t... Is>
669   decltype(auto)
670   call_call_type_operator_parentheses_with_tuple(const slot_type& _A_slot, const std::tuple<T_arg...>& tuple,
671     std::index_sequence<Is...>) const
672   {
673     return (_A_slot)(std::get<Is>(tuple)...);
674   }
675 };
676
677 /** Abstracts signal emission.
678  * This template specialization implements an optimized emit()
679  * function for the case that no accumulator is used.
680  */
681 template <class T_return, class... T_arg>
682 struct signal_emit<T_return, void, T_arg...>
683 {
684   using self_type = signal_emit<T_return, void, T_arg...>;
685   using result_type = T_return;
686   using slot_type = slot<T_return(T_arg...)>;
687   using iterator_type = signal_impl::const_iterator_type;
688   using call_type = typename slot_type::call_type;
689
690   /** Executes a list of slots.
691    * The arguments are passed directly on to the slots.
692    * The return value of the last slot invoked is returned.
693    * @param first An iterator pointing to the first slot in the list.
694    * @param last An iterator pointing to the last slot in the list.   * @param _A_a Arguments to be passed on to the slots.
695    * @return The return value of the last slot invoked.
696    */
697   static decltype(auto) emit(signal_impl* impl, type_trait_take_t<T_arg>... _A_a)
698     {
699       if (!impl || impl->slots_.empty())
700         return T_return();
701         
702       signal_exec exec(impl);
703       T_return r_ = T_return(); 
704       
705       //Use this scope to make sure that "slots" is destroyed before "exec" is destroyed.
706       //This avoids a leak on MSVC++ - see http://bugzilla.gnome.org/show_bug.cgi?id=306249
707       { 
708         temp_slot_list slots(impl->slots_);
709         iterator_type it = slots.begin();
710         for (; it != slots.end(); ++it)
711           if (!it->empty() && !it->blocked()) break;
712           
713         if (it == slots.end())
714           return T_return(); // note that 'T_return r_();' doesn't work => define 'r_' after this line and initialize as follows:
715   
716         r_ = (reinterpret_cast<call_type>(it->rep_->call_))(it->rep_, _A_a...);
717         for (++it; it != slots.end(); ++it)
718           {
719             if (it->empty() || it->blocked())
720               continue;
721             r_ = (reinterpret_cast<call_type>(it->rep_->call_))(it->rep_, _A_a...);
722           }
723       }
724       
725       return r_;
726     }
727
728   /** Executes a list of slots using an accumulator of type @e T_accumulator in reverse order.
729    * The arguments are passed directly on to the slots.
730    * @param _A_a%1 Argument to be passed on to the slots.
731    * @return The return value of the last slot invoked.
732    */
733   static decltype(auto) emit_reverse(signal_impl* impl, type_trait_take_t<T_arg>... _A_a)
734     {
735       if (!impl || impl->slots_.empty())
736         return T_return();
737         
738       signal_exec exec(impl);
739       T_return r_ = T_return(); 
740       
741       //Use this scope to make sure that "slots" is destroyed before "exec" is destroyed.
742       //This avoids a leak on MSVC++ - see http://bugzilla.gnome.org/show_bug.cgi?id=306249
743       { 
744         using reverse_iterator_type = std::reverse_iterator<signal_impl::iterator_type>;
745
746         temp_slot_list slots(impl->slots_);
747         reverse_iterator_type it(slots.end());
748         for (; it != reverse_iterator_type(slots.begin()); ++it)
749           if (!it->empty() && !it->blocked()) break;
750           
751         if (it == reverse_iterator_type(slots.begin()))
752           return T_return(); // note that 'T_return r_();' doesn't work => define 'r_' after this line and initialize as follows:
753   
754         r_ = (reinterpret_cast<call_type>(it->rep_->call_))(it->rep_, _A_a...);
755         for (++it; it != reverse_iterator_type(slots.begin()); ++it)
756           {
757             if (it->empty() || it->blocked())
758               continue;
759             r_ = (reinterpret_cast<call_type>(it->rep_->call_))(it->rep_, _A_a...);
760           }
761       }
762       
763       return r_;
764     }
765 };
766
767 /** Abstracts signal emission.
768  * This template specialization implements an optimized emit()
769  * function for the case that no accumulator is used and the
770  * return type is @p void.
771  */
772 template <class... T_arg>
773 struct signal_emit<void, void, T_arg...>
774 {
775   using self_type = signal_emit<void, void, T_arg...>;
776   using result_type = void;
777   using slot_type = slot<void(T_arg...)>;
778   using iterator_type = signal_impl::const_iterator_type;
779   using call_type = typename slot_type::call_type;
780
781   /** Executes a list of slots using an accumulator of type @e T_accumulator.   * The arguments are passed directly on to the slots.
782    * @param _A_a Arguments to be passed on to the slots.
783    */
784   static decltype(auto) emit(signal_impl* impl, type_trait_take_t<T_arg>... _A_a)
785     {
786       if (!impl || impl->slots_.empty()) return;
787       signal_exec exec(impl);
788       temp_slot_list slots(impl->slots_);
789
790       for (iterator_type it = slots.begin(); it != slots.end(); ++it)
791         {
792           if (it->empty() || it->blocked())
793             continue;
794           (reinterpret_cast<call_type>(it->rep_->call_))(it->rep_, _A_a...);
795         }
796     }
797
798   /** Executes a list of slots using an accumulator of type @e T_accumulator in reverse order.   * The arguments are passed directly on to the slots.
799    * @param first An iterator pointing to the first slot in the list.
800    * @param last An iterator pointing to the last slot in the list.   * @param _A_a Arguments to be passed on to the slots.
801    */
802   static decltype(auto) emit_reverse(signal_impl* impl, type_trait_take_t<T_arg>... _A_a)
803     {
804       if (!impl || impl->slots_.empty()) return;
805       signal_exec exec(impl);
806       temp_slot_list slots(impl->slots_);
807
808       using reverse_iterator_type = std::reverse_iterator<signal_impl::iterator_type>;
809
810       for (reverse_iterator_type it = reverse_iterator_type(slots.end()); it != reverse_iterator_type(slots.begin()); ++it)
811         {
812           if (it->empty() || it->blocked())
813             continue;
814           (reinterpret_cast<call_type>(it->rep_->call_))(it->rep_, _A_a...);
815         }
816     }
817 };
818
819
820
821 } /* namespace internal */
822
823
824 /** Signal declaration.
825  * signal_with_accumulator can be used to connect() slots that are invoked
826  * during subsequent calls to emit(). Any functor or slot
827  * can be passed into connect(). It is converted into a slot
828  * implicitly.
829  *
830  * If you want to connect one signal to another, use make_slot()
831  * to retrieve a functor that emits the signal when invoked.
832  *
833  * Be careful if you directly pass one signal into the connect()
834  * method of another: a shallow copy of the signal is made and
835  * the signal's slots are not disconnected until both the signal
836  * and its clone are destroyed, which is probably not what you want!
837  *
838  * An STL-style list interface for the signal's list of slots
839  * can be retrieved with slots(). This interface supports
840  * iteration, insertion and removal of slots.
841  *
842  * The following template arguments are used:
843  * - @e T_return The desired return type for the emit() function (may be overridden by the accumulator). * - @e T_arg Argument types used in the definition of emit().
844  * - @e T_accumulator The accumulator type used for emission. The default
845  * @p void means that no accumulator should be used, for example if signal
846  * emission returns the return value of the last slot invoked.
847  *
848  * @ingroup signal
849  */
850 template <class T_return, class T_accumulator, class... T_arg>
851 class signal_with_accumulator
852   : public signal_base
853 {
854 public:
855   using emitter_type = internal::signal_emit<T_return, T_accumulator, T_arg...>;
856   using result_type = typename emitter_type::result_type;
857   using slot_type = slot<T_return(T_arg...)>;
858   using slot_list_type = slot_list<slot_type>;
859   using iterator = typename slot_list_type::iterator;
860   using const_iterator = typename slot_list_type::const_iterator;
861   using reverse_iterator = typename slot_list_type::reverse_iterator;
862   using const_reverse_iterator = typename slot_list_type::const_reverse_iterator;
863
864   /** Add a slot to the list of slots.
865    * Any functor or slot may be passed into connect().
866    * It will be converted into a slot implicitly.
867    * The returned iterator may be stored for disconnection
868    * of the slot at some later point. It stays valid until
869    * the slot is removed from the list of slots. The iterator
870    * can also be implicitly converted into a sigc::connection object
871    * that may be used safely beyond the life time of the slot.
872    *
873    * std::function<> and C++11 lambda expressions are functors.
874    * These are examples of functors that can be connected to a signal.
875    *
876    * %std::bind() creates a functor, but this functor typically has an
877    * %operator()() which is a variadic template.
878    * Our functor_trait can't deduce the result type
879    * of such a functor. If you first assign the return value of %std::bind()
880    * to a std::function, you can connect the std::function to a signal.
881    *
882    * @param slot_ The slot to add to the list of slots.
883    * @return An iterator pointing to the new slot in the list.
884    */
885   iterator connect(const slot_type& slot_)
886     { return iterator(signal_base::connect(static_cast<const slot_base&>(slot_))); }
887
888   /** Add a slot to the list of slots.
889    * @see connect(const slot_type& slot_).
890    *
891    * @newin{2,8}
892    */
893   iterator connect(slot_type&& slot_)
894     { return iterator(signal_base::connect(std::move(static_cast<slot_base&>(slot_)))); }
895
896   /** Triggers the emission of the signal.
897    * During signal emission all slots that have been connected
898    * to the signal are invoked unless they are manually set into
899    * a blocking state. The parameters are passed on to the slots.
900    * If @e T_accumulated is not @p void, an accumulator of this type
901    * is used to process the return values of the slot invocations.
902    * Otherwise, the return value of the last slot invoked is returned.
903    * @param _A_a Arguments to be passed on to the slots.
904    * @return The accumulated return values of the slot invocations.
905    */
906   decltype(auto) emit(type_trait_take_t<T_arg>... _A_a) const
907     { return emitter_type::emit(impl_, _A_a...); }
908
909   /** Triggers the emission of the signal in reverse order (see emit()). */
910   decltype(auto) emit_reverse(type_trait_take_t<T_arg>... _A_a) const
911     { return emitter_type::emit_reverse(impl_, _A_a...); }
912
913   /** Triggers the emission of the signal (see emit()). */
914   decltype(auto) operator()(type_trait_take_t<T_arg>... _A_a) const
915     { return emit(_A_a...); }
916
917   /** Creates a functor that calls emit() on this signal.
918    * @code
919    * sigc::mem_fun(mysignal, &sigc::signal_with_accumulator::emit)
920    * @endcode
921    * yields the same result.
922    * @return A functor that calls emit() on this signal.
923    */
924   decltype(auto) make_slot() const
925     {
926       return bound_mem_functor<
927         result_type (signal_with_accumulator::*)(type_trait_take_t<T_arg>...) const,
928         type_trait_take_t<T_arg>...>(*this, &signal_with_accumulator::emit);
929     }
930
931   /** Creates an STL-style interface for the signal's list of slots.
932    * This interface supports iteration, insertion and removal of slots.
933    * @return An STL-style interface for the signal's list of slots.
934    */
935   slot_list_type slots()
936     { return slot_list_type(impl()); }
937
938   /** Creates an STL-style interface for the signal's list of slots.
939    * This interface supports iteration, insertion and removal of slots.
940    * @return An STL-style interface for the signal's list of slots.
941    */
942   const slot_list_type slots() const
943     { return slot_list_type(const_cast<signal_with_accumulator*>(this)->impl()); }
944
945   signal_with_accumulator() {}
946
947   signal_with_accumulator(const signal_with_accumulator& src)
948     : signal_base(src) {}
949
950   signal_with_accumulator(signal_with_accumulator&& src)
951     : signal_base(std::move(src)) {}
952
953   signal_with_accumulator& operator=(const signal_with_accumulator& src)
954   {
955     signal_base::operator=(src);
956     return *this;
957   }
958
959   signal_with_accumulator& operator=(signal_with_accumulator&& src)
960   {
961     signal_base::operator=(std::move(src));
962     return *this;
963   }
964 };
965
966
967 /** signal can be used to connect() slots that are invoked
968  * during subsequent calls to emit(). Any functor or slot
969  * can be passed into connect(). It is converted into a slot
970  * implicitly.
971  *
972  * If you want to connect one signal to another, use make_slot()
973  * to retrieve a functor that emits the signal when invoked.
974  *
975  * Be careful if you directly pass one signal into the connect()
976  * method of another: a shallow copy of the signal is made and
977  * the signal's slots are not disconnected until both the signal
978  * and its clone are destroyed, which is probably not what you want!
979  *
980  * An STL-style list interface for the signal's list of slots
981  * can be retrieved with slots(). This interface supports
982  * iteration, insertion and removal of slots.
983  *
984  * The template arguments determine the function signature of
985  * the emit() function:
986  * - @e T_return The desired return type of the emit() function. * - @e T_arg Argument types used in the definition of emit().
987  *
988  * For instance, to declare a signal whose connected slot returns void and takes
989  * two parameters of bool and int:
990  * @code
991  * sigc::signal<void(bool, int)> some_signal;
992  * @endcode
993  *
994  * To specify an accumulator type the nested class signal::accumulated can be used.
995  *
996  * @par Example:
997  * @code
998  * void foo(int) {}
999  * sigc::signal<void, long> sig;
1000  * sig.connect(sigc::ptr_fun(&foo));
1001  * sig.emit(19);
1002  * @endcode
1003  *
1004  * @ingroup signal
1005  */
1006 template <class T_return, class... T_arg>
1007 class signal;
1008
1009 template <class T_return, class... T_arg>
1010 class signal<T_return(T_arg...)>
1011   : public signal_with_accumulator<T_return, void, T_arg...>
1012 {
1013 public:
1014   using accumulator_type = void;
1015
1016   /** Like sigc::signal but the additional template parameter @e T_accumulator
1017    * defines the accumulator type that should be used.
1018    *
1019    * An accumulator is a functor that uses a pair of special iterators
1020    * to step through a list of slots and calculate a return value
1021    * from the results of the slot invokations. The iterators' operator*()
1022    * executes the slot. The return value is buffered, so that in an expression
1023    * like @code a = (*i) * (*i); @endcode the slot is executed only once.
1024    * The accumulator must define its return value as @p result_type.
1025    *
1026    * @par Example 1:
1027    * This accumulator calculates the arithmetic mean value:
1028    * @code
1029    * struct arithmetic_mean_accumulator
1030    * {
1031    *   using result_type = double;
1032    *   template<typename T_iterator>
1033    *   result_type operator()(T_iterator first, T_iterator last) const
1034    *   {
1035    *     result_type value_ = 0;
1036    *     int n_ = 0;
1037    *     for (; first != last; ++first, ++n_)
1038    *       value_ += *first;
1039    *     return value_ / n_;
1040    *   }
1041    * };
1042    * @endcode
1043    *
1044    * @par Example 2:
1045    * This accumulator stops signal emission when a slot returns zero:
1046    * @code
1047    * struct interruptable_accumulator
1048    * {
1049    *   using result_type = bool;
1050    *   template<typename T_iterator>
1051    *   result_type operator()(T_iterator first, T_iterator last) const
1052    *   {
1053    *     for (; first != last; ++first, ++n_)
1054    *       if (!*first) return false;
1055    *     return true;
1056    *   }
1057    * };
1058    * @endcode
1059    *
1060    * @ingroup signal
1061    */
1062   template <class T_accumulator>
1063   class accumulated
1064     : public signal_with_accumulator<T_return, T_accumulator, T_arg...>
1065   {
1066   public:
1067     accumulated() {}
1068     accumulated(const accumulated& src)
1069       : signal_with_accumulator<T_return, T_accumulator, T_arg...>(src) {}
1070   };
1071
1072   signal() {}
1073
1074   signal(const signal& src)
1075     : signal_with_accumulator<T_return, accumulator_type, T_arg...>(src) {}
1076
1077   signal(signal&& src)
1078     : signal_with_accumulator<T_return, accumulator_type, T_arg...>(std::move(src)) {}
1079
1080   signal& operator=(const signal& src)
1081   {
1082     signal_with_accumulator<T_return, accumulator_type, T_arg...>::operator=(src);
1083     return *this;
1084   }
1085
1086   signal& operator=(signal&& src)
1087   {
1088     signal_with_accumulator<T_return, accumulator_type, T_arg...>::operator=(std::move(src));
1089     return *this;
1090   }
1091 };
1092
1093
1094
1095 } /* namespace sigc */
1096
1097 #endif /* _SIGC_SIGNAL_H_ */