@@ -372,7 +372,7 @@ struct signal_emit<void, void, T_arg...>
372
372
} /* namespace internal */
373
373
374
374
/* * Signal declaration.
375
- * signal_with_accumulator can be used to connect() slots that are invoked
375
+ * % signal_with_accumulator can be used to connect() slots that are invoked
376
376
* during subsequent calls to emit(). Any functor or slot
377
377
* can be passed into connect(). It is converted into a slot
378
378
* implicitly.
@@ -462,10 +462,11 @@ class signal_with_accumulator : public signal_base
462
462
463
463
/* * Creates a functor that calls emit() on this signal.
464
464
*
465
- * @note %sigc::signal does not derive from sigc::trackable in sigc++3 .
466
- * If you connect the returned functor (calling %emit() on signal1) to
467
- * another signal (signal2) and then delete signal1, you must manually
465
+ * @note %sigc::signal does not derive from sigc::trackable.
466
+ * If you connect the returned functor that calls %emit() on signal1,
467
+ * to another signal (signal2) and then delete signal1, you must manually
468
468
* disconnect signal1 from signal2 before you delete signal1.
469
+ * Alternatively, make a slot of a sigc::trackable_signal.
469
470
*
470
471
* @code
471
472
* sigc::mem_fun(mysignal, &sigc::signal_with_accumulator::emit)
@@ -517,7 +518,8 @@ class signal_with_accumulator : public signal_base
517
518
*
518
519
* The template arguments determine the function signature of
519
520
* the emit() function:
520
- * - @e T_return The desired return type of the emit() function. * - @e T_arg Argument types used in
521
+ * - @e T_return The desired return type of the emit() function.
522
+ * - @e T_arg Argument types used in
521
523
* the definition of emit().
522
524
*
523
525
* For instance, to declare a signal whose connected slot returns void and takes
@@ -531,7 +533,7 @@ class signal_with_accumulator : public signal_base
531
533
* @par Example:
532
534
* @code
533
535
* void foo(int) {}
534
- * sigc::signal<void, long> sig;
536
+ * sigc::signal<void( long) > sig;
535
537
* sig.connect(sigc::ptr_fun(&foo));
536
538
* sig.emit(19);
537
539
* @endcode
@@ -625,6 +627,283 @@ class signal<T_return(T_arg...)> : public signal_with_accumulator<T_return, void
625
627
}
626
628
};
627
629
630
+ // TODO: When we can break ABI, let signal_base derive from trackable, as in sigc++2,
631
+ // and delete trackable_signal_with_accumulator and trackable_signal.
632
+ // https://github.com/libsigcplusplus/libsigcplusplus/issues/80
633
+
634
+ /* * Signal declaration.
635
+ * %trackable_signal_with_accumulator can be used to connect() slots that are invoked
636
+ * during subsequent calls to emit(). Any functor or slot
637
+ * can be passed into connect(). It is converted into a slot implicitly.
638
+ *
639
+ * If you want to connect one signal to another, use make_slot()
640
+ * to retrieve a functor that emits the signal when invoked.
641
+ *
642
+ * Be careful if you directly pass one signal into the connect()
643
+ * method of another: a shallow copy of the signal is made and
644
+ * the signal's slots are not disconnected until both the signal
645
+ * and its clone are destroyed, which is probably not what you want!
646
+ *
647
+ * The following template arguments are used:
648
+ * - @e T_return The desired return type for the emit() function (may be overridden by the
649
+ * accumulator).
650
+ * - @e T_arg Argument types used in the definition of emit().
651
+ * - @e T_accumulator The accumulator type used for emission. The default
652
+ * @p void means that no accumulator should be used, for example if signal
653
+ * emission returns the return value of the last slot invoked.
654
+ *
655
+ * @newin{3,4}
656
+ *
657
+ * @ingroup signal
658
+ */
659
+ template <typename T_return, typename T_accumulator, typename ... T_arg>
660
+ class trackable_signal_with_accumulator
661
+ : public signal_base
662
+ , public trackable
663
+ {
664
+ public:
665
+ using slot_type = slot<T_return(T_arg...)>;
666
+
667
+ /* * Add a slot to the list of slots.
668
+ * Any functor or slot may be passed into connect().
669
+ * It will be converted into a slot implicitly.
670
+ * The returned connection may be stored for disconnection
671
+ * of the slot at some later point. It stays valid until
672
+ * the slot is disconnected from the signal.
673
+ * std::function<> and C++11 lambda expressions are functors.
674
+ * These are examples of functors that can be connected to a signal.
675
+ *
676
+ * %std::bind() creates a functor, but this functor typically has an
677
+ * %operator()() which is a variadic template.
678
+ * Our functor_trait can't deduce the result type
679
+ * of such a functor. If you first assign the return value of %std::bind()
680
+ * to a std::function, you can connect the std::function to a signal.
681
+ *
682
+ * @param slot_ The slot to add to the list of slots.
683
+ * @return A connection.
684
+ */
685
+ connection connect (const slot_type& slot_)
686
+ {
687
+ auto iter = signal_base::connect (slot_);
688
+ auto & slot_base = *iter;
689
+ return connection (slot_base);
690
+ }
691
+
692
+ /* * Add a slot to the list of slots.
693
+ * @see connect(const slot_type& slot_).
694
+ */
695
+ connection connect (slot_type&& slot_)
696
+ {
697
+ auto iter = signal_base::connect (std::move (slot_));
698
+ auto & slot_base = *iter;
699
+ return connection (slot_base);
700
+ }
701
+
702
+ /* * Triggers the emission of the signal.
703
+ * During signal emission all slots that have been connected
704
+ * to the signal are invoked unless they are manually set into
705
+ * a blocking state. The parameters are passed on to the slots.
706
+ * If @e T_accumulated is not @p void, an accumulator of this type
707
+ * is used to process the return values of the slot invocations.
708
+ * Otherwise, the return value of the last slot invoked is returned.
709
+ * @param a Arguments to be passed on to the slots.
710
+ * @return The accumulated return values of the slot invocations.
711
+ */
712
+ decltype (auto ) emit(type_trait_take_t <T_arg>... a) const
713
+ {
714
+ using emitter_type = internal::signal_emit<T_return, T_accumulator, T_arg...>;
715
+ return emitter_type::emit (impl_, std::forward<type_trait_take_t <T_arg>>(a)...);
716
+ }
717
+
718
+ /* * Triggers the emission of the signal (see emit()). */
719
+ decltype (auto ) operator ()(type_trait_take_t <T_arg>... a) const
720
+ {
721
+ return emit (std::forward<type_trait_take_t <T_arg>>(a)...);
722
+ }
723
+
724
+ /* * Creates a functor that calls emit() on this signal.
725
+ *
726
+ * @code
727
+ * sigc::mem_fun(mysignal, &sigc::trackable_signal_with_accumulator::emit)
728
+ * @endcode
729
+ * yields the same result.
730
+ * @return A functor that calls emit() on this signal.
731
+ */
732
+ decltype (auto ) make_slot() const
733
+ {
734
+ // TODO: Instead use std::invoke_result<> on the static emitter_type::emit()
735
+ using result_type = typename internal::member_method_result<
736
+ decltype (&trackable_signal_with_accumulator::emit)>::type;
737
+ return bound_mem_functor<result_type (trackable_signal_with_accumulator::*)(
738
+ type_trait_take_t <T_arg>...) const ,
739
+ type_trait_take_t <T_arg>...>(*this , &trackable_signal_with_accumulator::emit);
740
+ }
741
+
742
+ trackable_signal_with_accumulator () = default ;
743
+
744
+ trackable_signal_with_accumulator (const trackable_signal_with_accumulator& src)
745
+ : signal_base(src), trackable(src)
746
+ {
747
+ }
748
+
749
+ trackable_signal_with_accumulator (trackable_signal_with_accumulator&& src)
750
+ : signal_base(std::move(src)), trackable(std::move(src))
751
+ {
752
+ }
753
+
754
+ trackable_signal_with_accumulator& operator =(const trackable_signal_with_accumulator& src)
755
+ {
756
+ signal_base::operator =(src);
757
+ // Don't call trackable::operator=(src).
758
+ // It calls notify_callbacks(). This signal is not destroyed.
759
+ return *this ;
760
+ }
761
+
762
+ trackable_signal_with_accumulator& operator =(trackable_signal_with_accumulator&& src)
763
+ {
764
+ signal_base::operator =(std::move (src));
765
+ if (src.impl_ != impl_)
766
+ src.notify_callbacks ();
767
+ // Don't call trackable::operator=(std::move(src)).
768
+ // It calls notify_callbacks(). This signal is not destroyed.
769
+ return *this ;
770
+ }
771
+ };
772
+
773
+ /* * %trackable_signal can be used to connect() slots that are invoked
774
+ * during subsequent calls to emit(). Any functor or slot
775
+ * can be passed into connect(). It is converted into a slot
776
+ * implicitly.
777
+ *
778
+ * If you want to connect one signal to another, use make_slot()
779
+ * to retrieve a functor that emits the signal when invoked.
780
+ *
781
+ * Be careful if you directly pass one signal into the connect()
782
+ * method of another: a shallow copy of the signal is made and
783
+ * the signal's slots are not disconnected until both the signal
784
+ * and its clone are destroyed, which is probably not what you want!
785
+ *
786
+ * The template arguments determine the function signature of
787
+ * the emit() function:
788
+ * - @e T_return The desired return type of the emit() function.
789
+ * - @e T_arg Argument types used in
790
+ * the definition of emit().
791
+ *
792
+ * For instance, to declare a %trackable_signal whose connected slot returns void and takes
793
+ * two parameters of bool and int:
794
+ * @code
795
+ * sigc::trackable_signal<void(bool, int)> some_signal;
796
+ * @endcode
797
+ *
798
+ * To specify an accumulator type the nested class trackable_signal::accumulated can be used.
799
+ *
800
+ * @par Example:
801
+ * @code
802
+ * void foo(int) {}
803
+ * sigc::trackable_signal<void(long)> sig;
804
+ * sig.connect(sigc::ptr_fun(&foo));
805
+ * sig.emit(19);
806
+ * @endcode
807
+ *
808
+ * @newin{3,4}
809
+ *
810
+ * @ingroup signal
811
+ */
812
+ #ifndef DOXYGEN_SHOULD_SKIP_THIS
813
+ template <typename T_return, typename ... T_arg>
814
+ class trackable_signal ;
815
+ #endif // DOXYGEN_SHOULD_SKIP_THIS
816
+
817
+ template <typename T_return, typename ... T_arg>
818
+ class trackable_signal <T_return(T_arg...)>
819
+ : public trackable_signal_with_accumulator<T_return, void , T_arg...>
820
+ {
821
+ public:
822
+ using accumulator_type = void ;
823
+
824
+ /* * Like @ref sigc::trackable_signal<T_return(T_arg...)> "sigc::trackable_signal"
825
+ * but the additional template parameter @e T_accumulator defines the accumulator
826
+ * type that should be used.
827
+ *
828
+ * An accumulator is a functor that uses a pair of special iterators
829
+ * to step through a list of slots and calculate a return value
830
+ * from the results of the slot invocations. The iterators' operator*()
831
+ * executes the slot. The return value is buffered, so that in an expression
832
+ * like @code a = (*i) * (*i); @endcode the slot is executed only once.
833
+ *
834
+ * @par Example 1:
835
+ * This accumulator calculates the arithmetic mean value:
836
+ * @code
837
+ * struct arithmetic_mean_accumulator
838
+ * {
839
+ * template<typename T_iterator>
840
+ * double operator()(T_iterator first, T_iterator last) const
841
+ * {
842
+ * double value_ = 0;
843
+ * int n_ = 0;
844
+ * for (; first != last; ++first, ++n_)
845
+ * value_ += *first;
846
+ * return value_ / n_;
847
+ * }
848
+ * };
849
+ * @endcode
850
+ *
851
+ * @par Example 2:
852
+ * This accumulator stops signal emission when a slot returns zero:
853
+ * @code
854
+ * struct interruptable_accumulator
855
+ * {
856
+ * template<typename T_iterator>
857
+ * bool operator()(T_iterator first, T_iterator last) const
858
+ * {
859
+ * for (; first != last; ++first, ++n_)
860
+ * if (!*first) return false;
861
+ * return true;
862
+ * }
863
+ * };
864
+ * @endcode
865
+ *
866
+ * @newin{3,4}
867
+ *
868
+ * @ingroup signal
869
+ */
870
+ template <typename T_accumulator>
871
+ class accumulated : public trackable_signal_with_accumulator <T_return, T_accumulator, T_arg...>
872
+ {
873
+ public:
874
+ accumulated () = default ;
875
+ accumulated (const accumulated& src)
876
+ : trackable_signal_with_accumulator<T_return, T_accumulator, T_arg...>(src)
877
+ {
878
+ }
879
+ };
880
+
881
+ trackable_signal () = default ;
882
+
883
+ trackable_signal (const trackable_signal& src)
884
+ : trackable_signal_with_accumulator<T_return, accumulator_type, T_arg...>(src)
885
+ {
886
+ }
887
+
888
+ trackable_signal (trackable_signal&& src)
889
+ : trackable_signal_with_accumulator<T_return, accumulator_type, T_arg...>(std::move(src))
890
+ {
891
+ }
892
+
893
+ trackable_signal& operator =(const trackable_signal& src)
894
+ {
895
+ trackable_signal_with_accumulator<T_return, accumulator_type, T_arg...>::operator =(src);
896
+ return *this ;
897
+ }
898
+
899
+ trackable_signal& operator =(trackable_signal&& src)
900
+ {
901
+ trackable_signal_with_accumulator<T_return, accumulator_type, T_arg...>::operator =(
902
+ std::move (src));
903
+ return *this ;
904
+ }
905
+ };
906
+
628
907
} /* namespace sigc */
629
908
630
909
#endif /* SIGC_SIGNAL_H */
0 commit comments