2 * Copyright 2002-2016, The libsigc++ Development Team
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.
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.
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
20 #ifndef _SIGC_SIGNAL_H_
21 #define _SIGC_SIGNAL_H_
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>
34 /** STL-style iterator for slot_list.
38 template <typename T_slot>
41 using size_type = std::size_t;
42 using difference_type = std::ptrdiff_t;
43 using iterator_category = std::bidirectional_iterator_tag;
45 using slot_type = T_slot;
47 using value_type = T_slot;
48 using pointer = T_slot*;
49 using reference = T_slot&;
51 using iterator_type = typename internal::signal_impl::iterator_type;
56 explicit slot_iterator(const iterator_type& i)
59 reference operator*() const
60 { return static_cast<reference>(*i_); }
62 pointer operator->() const
63 { return &(operator*()); }
65 slot_iterator& operator++()
71 slot_iterator operator++(int)
73 slot_iterator __tmp(*this);
78 slot_iterator& operator--()
84 slot_iterator operator--(int)
86 slot_iterator __tmp(*this);
91 bool operator == (const slot_iterator& other) const
92 { return i_ == other.i_; }
94 bool operator != (const slot_iterator& other) const
95 { return i_ != other.i_; }
100 /** STL-style const iterator for slot_list.
104 template <typename T_slot>
105 struct slot_const_iterator
107 using size_type = std::size_t;
108 using difference_type = std::ptrdiff_t;
109 using iterator_category = std::bidirectional_iterator_tag;
111 using slot_type = T_slot;
113 using value_type = T_slot;
114 using pointer = const T_slot*;
115 using reference = const T_slot&;
117 using iterator_type = typename internal::signal_impl::const_iterator_type;
119 slot_const_iterator()
122 explicit slot_const_iterator(const iterator_type& i)
125 reference operator*() const
126 { return static_cast<reference>(*i_); }
128 pointer operator->() const
129 { return &(operator*()); }
131 slot_const_iterator& operator++()
137 slot_const_iterator operator++(int)
139 slot_const_iterator __tmp(*this);
144 slot_const_iterator& operator--()
150 slot_const_iterator operator--(int)
152 slot_const_iterator __tmp(*this);
157 bool operator == (const slot_const_iterator& other) const
158 { return i_ == other.i_; }
160 bool operator != (const slot_const_iterator& other) const
161 { return i_ != other.i_; }
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.
174 template <class T_slot>
177 using slot_type = T_slot;
179 using reference = slot_type&;
180 using const_reference = const slot_type&;
182 using iterator = slot_iterator<slot_type>;
183 using const_iterator = slot_const_iterator<slot_type>;
185 using reverse_iterator = std::reverse_iterator<iterator>;
186 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
191 explicit slot_list(internal::signal_impl* __list)
195 { return iterator(list_->slots_.begin()); }
197 const_iterator begin() const
198 { return const_iterator(list_->slots_.begin()); }
201 { return iterator(list_->slots_.end()); }
203 const_iterator end() const
204 { return const_iterator(list_->slots_.end()); }
206 reverse_iterator rbegin()
207 { return reverse_iterator(end()); }
209 const_reverse_iterator rbegin() const
210 { return const_reverse_iterator(end()); }
212 reverse_iterator rend()
213 { return reverse_iterator(begin()); }
215 const_reverse_iterator rend() const
216 { return const_reverse_iterator(begin()); }
221 const_reference front() const
225 { return *(--end()); }
227 const_reference back() const
228 { return *(--end()); }
230 iterator insert(iterator i, const slot_type& slot_)
231 { return iterator(list_->insert(i.i_, static_cast<const slot_base&>(slot_))); }
233 iterator insert(iterator i, slot_type&& slot_)
234 { return iterator(list_->insert(i.i_, std::move(static_cast<slot_base&>(slot_)))); }
236 void push_front(const slot_type& c)
237 { insert(begin(), c); }
239 void push_front(slot_type&& c)
240 { insert(begin(), std::move(c)); }
242 void push_back(const slot_type& c)
243 { insert(end(), c); }
245 void push_back(slot_type&& c)
246 { insert(end(), std::move(c)); }
248 iterator erase(iterator i)
249 { return iterator(list_->erase(i.i_)); }
251 iterator erase(iterator first_, iterator last_)
253 while (first_ != last_)
254 first_ = erase(first_);
268 internal::signal_impl* list_;
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.
279 template <class T_emitter, class T_result = typename T_emitter::result_type>
280 struct slot_iterator_buf
282 using size_type = std::size_t;
283 using difference_type = std::ptrdiff_t;
284 using iterator_category = std::bidirectional_iterator_tag;
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*;
292 using emitter_type = T_emitter;
293 using result_type = T_result;
294 using slot_type = typename T_emitter::slot_type;
296 using iterator_type = signal_impl::const_iterator_type;
299 : c_(nullptr), invoked_(false) {}
301 slot_iterator_buf(const iterator_type& i, const emitter_type* c)
302 : i_(i), c_(c), invoked_(false) {}
304 decltype(auto) operator*() const
306 if (!i_->empty() && !i_->blocked() && !invoked_)
308 r_ = (*c_)(static_cast<const slot_type&>(*i_));
314 slot_iterator_buf& operator++()
321 slot_iterator_buf operator++(int)
323 slot_iterator_buf __tmp(*this);
329 slot_iterator_buf& operator--()
336 slot_iterator_buf operator--(int)
338 slot_iterator_buf __tmp(*this);
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. */
350 bool operator != (const slot_iterator_buf& other) const
351 { return (c_ && (i_ != other.i_)); }
355 const emitter_type* c_;
356 mutable result_type r_;
357 mutable bool invoked_;
360 /** Template specialization of slot_iterator_buf for void return signals.
362 template <class T_emitter>
363 struct slot_iterator_buf<T_emitter, void>
365 using size_type = std::size_t;
366 using difference_type = std::ptrdiff_t;
367 using iterator_category = std::bidirectional_iterator_tag;
369 using emitter_type = T_emitter;
370 using result_type = void;
371 using slot_type = typename T_emitter::slot_type;
373 using iterator_type = signal_impl::const_iterator_type;
376 : c_(nullptr), invoked_(false) {}
378 slot_iterator_buf(const iterator_type& i, const emitter_type* c)
379 : i_(i), c_(c), invoked_(false) {}
381 void operator*() const
383 if (!i_->empty() && !i_->blocked() && !invoked_)
385 (*c_)(static_cast<const slot_type&>(*i_));
390 slot_iterator_buf& operator++()
397 slot_iterator_buf operator++(int)
399 slot_iterator_buf __tmp(*this);
405 slot_iterator_buf& operator--()
412 slot_iterator_buf operator--(int)
414 slot_iterator_buf __tmp(*this);
420 bool operator == (const slot_iterator_buf& other) const
421 { return i_ == other.i_; }
423 bool operator != (const slot_iterator_buf& other) const
424 { return i_ != other.i_; }
428 const emitter_type* c_;
429 mutable bool invoked_;
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
436 using size_type = std::size_t;
437 using difference_type = std::ptrdiff_t;
438 using iterator_category = std::bidirectional_iterator_tag;
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*;
446 using emitter_type = T_emitter;
447 using result_type = T_result;
448 using slot_type = typename T_emitter::slot_type;
450 using iterator_type = signal_impl::const_iterator_type;
452 slot_reverse_iterator_buf()
453 : c_(nullptr), invoked_(false) {}
455 slot_reverse_iterator_buf(const iterator_type& i, const emitter_type* c)
456 : i_(i), c_(c), invoked_(false) {}
458 decltype(auto) operator*() const
460 iterator_type __tmp(i_);
462 if (!__tmp->empty() && !__tmp->blocked() && !invoked_)
464 r_ = (*c_)(static_cast<const slot_type&>(*__tmp));
470 slot_reverse_iterator_buf& operator++()
477 slot_reverse_iterator_buf operator++(int)
479 slot_reverse_iterator_buf __tmp(*this);
485 slot_reverse_iterator_buf& operator--()
492 slot_reverse_iterator_buf operator--(int)
494 slot_reverse_iterator_buf __tmp(*this);
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. */
506 bool operator != (const slot_reverse_iterator_buf& other) const
507 { return (c_ && (i_ != other.i_)); }
511 const emitter_type* c_;
512 mutable result_type r_;
513 mutable bool invoked_;
516 /** Template specialization of slot_reverse_iterator_buf for void return signals.
518 template <class T_emitter>
519 struct slot_reverse_iterator_buf<T_emitter, void>
521 using size_type = std::size_t;
522 using difference_type = std::ptrdiff_t;
523 using iterator_category = std::bidirectional_iterator_tag;
525 using emitter_type = T_emitter;
526 using result_type = void;
527 using slot_type = typename T_emitter::slot_type;
529 using iterator_type = signal_impl::const_iterator_type;
531 slot_reverse_iterator_buf()
532 : c_(nullptr), invoked_(false) {}
534 slot_reverse_iterator_buf(const iterator_type& i, const emitter_type* c)
535 : i_(i), c_(c), invoked_(false) {}
537 void operator*() const
539 iterator_type __tmp(i_);
541 if (!__tmp->empty() && !__tmp->blocked() && !invoked_)
543 (*c_)(static_cast<const slot_type&>(*__tmp));
548 slot_reverse_iterator_buf& operator++()
555 slot_reverse_iterator_buf operator++(int)
557 slot_reverse_iterator_buf __tmp(*this);
563 slot_reverse_iterator_buf& operator--()
570 slot_reverse_iterator_buf operator--(int)
572 slot_reverse_iterator_buf __tmp(*this);
578 bool operator == (const slot_reverse_iterator_buf& other) const
579 { return i_ == other.i_; }
581 bool operator != (const slot_reverse_iterator_buf& other) const
582 { return i_ != other.i_; }
586 const emitter_type* c_;
587 mutable bool invoked_;
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.
597 template <class T_return, class T_accumulator, class... T_arg>
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;
607 /** Instantiates the class.
608 * The parameters are stored in member variables. operator()() passes
609 * the values on to some slot.
611 signal_emit(type_trait_take_t<T_arg>... _A_a)
614 /** Invokes a slot using the buffered parameter values.
615 * @param _A_slot Some slot to invoke.
616 * @return The slot's return value.
618 T_return operator()(const slot_type& _A_slot) const
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);
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.
629 static decltype(auto) emit(signal_impl* impl, type_trait_take_t<T_arg>... _A_a)
631 T_accumulator accumulator;
634 return accumulator(slot_iterator_buf_type(), slot_iterator_buf_type());
636 signal_exec exec(impl);
637 temp_slot_list slots(impl->slots_);
639 self_type self(_A_a...);
640 return accumulator(slot_iterator_buf_type(slots.begin(), &self),
641 slot_iterator_buf_type(slots.end(), &self));
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.
648 static decltype(auto) emit_reverse(signal_impl* impl, type_trait_take_t<T_arg>... _A_a)
650 T_accumulator accumulator;
653 return accumulator(slot_iterator_buf_type(), slot_iterator_buf_type());
655 signal_exec exec(impl);
656 temp_slot_list slots(impl->slots_);
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));
663 std::tuple<type_trait_take_t<T_arg>...> _A_a_;
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>
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
673 return (_A_slot)(std::get<Is>(tuple)...);
677 /** Abstracts signal emission.
678 * This template specialization implements an optimized emit()
679 * function for the case that no accumulator is used.
681 template <class T_return, class... T_arg>
682 struct signal_emit<T_return, void, T_arg...>
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;
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.
697 static decltype(auto) emit(signal_impl* impl, type_trait_take_t<T_arg>... _A_a)
699 if (!impl || impl->slots_.empty())
702 signal_exec exec(impl);
703 T_return r_ = T_return();
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
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;
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:
716 r_ = (reinterpret_cast<call_type>(it->rep_->call_))(it->rep_, _A_a...);
717 for (++it; it != slots.end(); ++it)
719 if (it->empty() || it->blocked())
721 r_ = (reinterpret_cast<call_type>(it->rep_->call_))(it->rep_, _A_a...);
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.
733 static decltype(auto) emit_reverse(signal_impl* impl, type_trait_take_t<T_arg>... _A_a)
735 if (!impl || impl->slots_.empty())
738 signal_exec exec(impl);
739 T_return r_ = T_return();
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
744 using reverse_iterator_type = std::reverse_iterator<signal_impl::iterator_type>;
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;
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:
754 r_ = (reinterpret_cast<call_type>(it->rep_->call_))(it->rep_, _A_a...);
755 for (++it; it != reverse_iterator_type(slots.begin()); ++it)
757 if (it->empty() || it->blocked())
759 r_ = (reinterpret_cast<call_type>(it->rep_->call_))(it->rep_, _A_a...);
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.
772 template <class... T_arg>
773 struct signal_emit<void, void, T_arg...>
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;
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.
784 static decltype(auto) emit(signal_impl* impl, type_trait_take_t<T_arg>... _A_a)
786 if (!impl || impl->slots_.empty()) return;
787 signal_exec exec(impl);
788 temp_slot_list slots(impl->slots_);
790 for (iterator_type it = slots.begin(); it != slots.end(); ++it)
792 if (it->empty() || it->blocked())
794 (reinterpret_cast<call_type>(it->rep_->call_))(it->rep_, _A_a...);
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.
802 static decltype(auto) emit_reverse(signal_impl* impl, type_trait_take_t<T_arg>... _A_a)
804 if (!impl || impl->slots_.empty()) return;
805 signal_exec exec(impl);
806 temp_slot_list slots(impl->slots_);
808 using reverse_iterator_type = std::reverse_iterator<signal_impl::iterator_type>;
810 for (reverse_iterator_type it = reverse_iterator_type(slots.end()); it != reverse_iterator_type(slots.begin()); ++it)
812 if (it->empty() || it->blocked())
814 (reinterpret_cast<call_type>(it->rep_->call_))(it->rep_, _A_a...);
821 } /* namespace internal */
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
830 * If you want to connect one signal to another, use make_slot()
831 * to retrieve a functor that emits the signal when invoked.
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!
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.
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.
850 template <class T_return, class T_accumulator, class... T_arg>
851 class signal_with_accumulator
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;
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.
873 * std::function<> and C++11 lambda expressions are functors.
874 * These are examples of functors that can be connected to a signal.
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.
882 * @param slot_ The slot to add to the list of slots.
883 * @return An iterator pointing to the new slot in the list.
885 iterator connect(const slot_type& slot_)
886 { return iterator(signal_base::connect(static_cast<const slot_base&>(slot_))); }
888 /** Add a slot to the list of slots.
889 * @see connect(const slot_type& slot_).
893 iterator connect(slot_type&& slot_)
894 { return iterator(signal_base::connect(std::move(static_cast<slot_base&>(slot_)))); }
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.
906 decltype(auto) emit(type_trait_take_t<T_arg>... _A_a) const
907 { return emitter_type::emit(impl_, _A_a...); }
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...); }
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...); }
917 /** Creates a functor that calls emit() on this signal.
919 * sigc::mem_fun(mysignal, &sigc::signal_with_accumulator::emit)
921 * yields the same result.
922 * @return A functor that calls emit() on this signal.
924 decltype(auto) make_slot() const
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);
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.
935 slot_list_type slots()
936 { return slot_list_type(impl()); }
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.
942 const slot_list_type slots() const
943 { return slot_list_type(const_cast<signal_with_accumulator*>(this)->impl()); }
945 signal_with_accumulator() {}
947 signal_with_accumulator(const signal_with_accumulator& src)
948 : signal_base(src) {}
950 signal_with_accumulator(signal_with_accumulator&& src)
951 : signal_base(std::move(src)) {}
953 signal_with_accumulator& operator=(const signal_with_accumulator& src)
955 signal_base::operator=(src);
959 signal_with_accumulator& operator=(signal_with_accumulator&& src)
961 signal_base::operator=(std::move(src));
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
972 * If you want to connect one signal to another, use make_slot()
973 * to retrieve a functor that emits the signal when invoked.
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!
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.
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().
988 * For instance, to declare a signal whose connected slot returns void and takes
989 * two parameters of bool and int:
991 * sigc::signal<void(bool, int)> some_signal;
994 * To specify an accumulator type the nested class signal::accumulated can be used.
999 * sigc::signal<void, long> sig;
1000 * sig.connect(sigc::ptr_fun(&foo));
1006 template <class T_return, class... T_arg>
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...>
1014 using accumulator_type = void;
1016 /** Like sigc::signal but the additional template parameter @e T_accumulator
1017 * defines the accumulator type that should be used.
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.
1027 * This accumulator calculates the arithmetic mean value:
1029 * struct arithmetic_mean_accumulator
1031 * using result_type = double;
1032 * template<typename T_iterator>
1033 * result_type operator()(T_iterator first, T_iterator last) const
1035 * result_type value_ = 0;
1037 * for (; first != last; ++first, ++n_)
1039 * return value_ / n_;
1045 * This accumulator stops signal emission when a slot returns zero:
1047 * struct interruptable_accumulator
1049 * using result_type = bool;
1050 * template<typename T_iterator>
1051 * result_type operator()(T_iterator first, T_iterator last) const
1053 * for (; first != last; ++first, ++n_)
1054 * if (!*first) return false;
1062 template <class T_accumulator>
1064 : public signal_with_accumulator<T_return, T_accumulator, T_arg...>
1068 accumulated(const accumulated& src)
1069 : signal_with_accumulator<T_return, T_accumulator, T_arg...>(src) {}
1074 signal(const signal& src)
1075 : signal_with_accumulator<T_return, accumulator_type, T_arg...>(src) {}
1077 signal(signal&& src)
1078 : signal_with_accumulator<T_return, accumulator_type, T_arg...>(std::move(src)) {}
1080 signal& operator=(const signal& src)
1082 signal_with_accumulator<T_return, accumulator_type, T_arg...>::operator=(src);
1086 signal& operator=(signal&& src)
1088 signal_with_accumulator<T_return, accumulator_type, T_arg...>::operator=(std::move(src));
1095 } /* namespace sigc */
1097 #endif /* _SIGC_SIGNAL_H_ */