[libsigcplusplus/libsigc++-2-10: 2/2] signal: Allow sigc::signal<R(Args...)> declaration, like std::function.



commit a625175a289339da59fee39c7b22e20432f152b7
Author: Murray Cumming <murrayc murrayc com>
Date:   Sat Mar 12 16:01:51 2016 +0100

    signal: Allow sigc::signal<R(Args...)> declaration, like std::function.
    
    By adding template specializations that repeats the signal*
    template declarations, though it would be good to avoid the repetition.
    
    Bug 763393

 sigc++/macros/signal.h.m4 |   93 +++++++++++++++++++++++++++++++++++++++++++++
 tests/test_signal.cc      |   10 +++++
 2 files changed, 103 insertions(+), 0 deletions(-)
---
diff --git a/sigc++/macros/signal.h.m4 b/sigc++/macros/signal.h.m4
index 157128a..98a28d5 100644
--- a/sigc++/macros/signal.h.m4
+++ b/sigc++/macros/signal.h.m4
@@ -555,6 +555,99 @@ ifelse($1, $2,[dnl
   }
 };
 
+/**
+ * This specialization allow use of the  sigc::signal<R(Args...)> syntax,
+ */
+template <LIST(class T_return, LOOP(class T_arg%1, $1))>
+class signal<T_return(LIST(LOOP(T_arg%1, $1)))>
+  : public signal$1<LIST(T_return, LOOP(T_arg%1, $1),nil)>
+{
+public:
+ifelse($1, $2,[dnl
+  /** Convenience wrapper for the numbered sigc::signal# templates.
+   * Like sigc::signal but the additional template parameter @e T_accumulator
+   * defines the accumulator type that should be used.
+   *
+   * An accumulator is a functor that uses a pair of special iterators
+   * to step through a list of slots and calculate a return value
+   * from the results of the slot invokations. The iterators' operator*()
+   * executes the slot. The return value is buffered, so that in an expression
+   * like @code a = (*i) * (*i); @endcode the slot is executed only once.
+   * The accumulator must define its return value as @p result_type.
+   *
+   * @par Example 1:
+   * This accumulator calculates the arithmetic mean value:
+   * @code
+   * struct arithmetic_mean_accumulator
+   * {
+   *   typedef double result_type;
+   *   template<typename T_iterator>
+   *   result_type operator()(T_iterator first, T_iterator last) const
+   *   {
+   *     result_type value_ = 0;
+   *     int n_ = 0;
+   *     for (; first != last; ++first, ++n_)
+   *       value_ += *first;
+   *     return value_ / n_;
+   *   }
+   * };
+   * @endcode
+   *
+   * @par Example 2:
+   * This accumulator stops signal emission when a slot returns zero:
+   * @code
+   * struct interruptable_accumulator
+   * {
+   *   typedef bool result_type;
+   *   template<typename T_iterator>
+   *   result_type operator()(T_iterator first, T_iterator last) const
+   *   {
+   *     for (; first != last; ++first, ++n_)
+   *       if (!*first) return false;
+   *     return true;
+   *   }
+   * };
+   * @endcode
+   *
+   * @ingroup signal
+],[
+  /** Convenience wrapper for the numbered sigc::signal$1 template.
+   * Like sigc::signal but the additional template parameter @e T_accumulator
+   * defines the accumulator type that should be used.
+])dnl
+   */
+  template <class T_accumulator>
+  class accumulated
+    : public signal$1<LIST(T_return, LOOP(T_arg%1, $1), T_accumulator)>
+  {
+  public:
+    accumulated() {}
+    accumulated(const accumulated& src)
+      : signal$1<LIST(T_return, LOOP(T_arg%1, $1), T_accumulator)>(src) {}
+  };
+
+  signal() {}
+
+  signal(const signal& src)
+    : signal$1<LIST(T_return, LOOP(T_arg%1, $1),nil)>(src) {}
+
+  signal(signal&& src)
+    : signal$1<LIST(T_return, LOOP(T_arg%1, $1),nil)>(std::move(src)) {}
+
+  signal& operator=(const signal& src)
+  {
+    signal$1<LIST(T_return, LOOP(T_arg%1, $1),nil)>::operator=(src);
+    return *this;
+  }
+
+  signal& operator=(signal&& src)
+  {
+    signal$1<LIST(T_return, LOOP(T_arg%1, $1),nil)>::operator=(std::move(src));
+    return *this;
+  }
+};
+
+
 ])
 
 divert(0)
diff --git a/tests/test_signal.cc b/tests/test_signal.cc
index 744acbe..bdd50dc 100644
--- a/tests/test_signal.cc
+++ b/tests/test_signal.cc
@@ -111,6 +111,15 @@ void test_make_slot()
   util->check_result(result_stream, "foo(int 3) bar(float 3) foo(int 3) ");
 }
 
+void test_std_function_style_syntax()
+{
+  sigc::signal<int(int)> sig;
+  sig.connect(sigc::ptr_fun(&foo));
+
+  sig(1);
+  util->check_result(result_stream, "foo(int 1) ");
+}
+
 } // end anonymous namespace
 
 int main(int argc, char* argv[])
@@ -125,6 +134,7 @@ int main(int argc, char* argv[])
   test_auto_disconnection();
   test_reference();
   test_make_slot();
+  test_std_function_style_syntax();
 
   return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]