[libsigcplusplus] slot: Allow sigc::slot<R(Args...)> declaration, like std::function.



commit 911398e6f70693833f515c44aec9899a092d9250
Author: Murray Cumming <murrayc murrayc com>
Date:   Fri Mar 11 10:26:56 2016 +0100

    slot: Allow sigc::slot<R(Args...)> declaration, like std::function.
    
    By adding a template specialization that repeats the main
    template declaration, though it would be good to avoid the repetition.
    
    Bug #763393

 sigc++/functors/slot.h |  111 ++++++++++++++++++++++++++++++++++++++++++++++++
 tests/test_slot.cc     |   13 ++++++
 2 files changed, 124 insertions(+), 0 deletions(-)
---
diff --git a/sigc++/functors/slot.h b/sigc++/functors/slot.h
index ab39a97..1259d1a 100644
--- a/sigc++/functors/slot.h
+++ b/sigc++/functors/slot.h
@@ -142,6 +142,11 @@ struct slot_call
  * sigc::slot<void, bool, int> some_slot;
  * @endcode
  *
+ * Alternatively, you may use a syntax similar to that used by std::function<>:
+ * @code
+ * sigc::slot<void(bool, int)> some_slot;
+ * @endcode
+ *
  * To use, simply assign the desired functor to the slot. If the functor
  * is not compatible with the parameter list defined with the template
  * arguments then compiler errors are triggered. When called, the slot
@@ -227,6 +232,112 @@ public:
   }
 };
 
+
+/** Converts an arbitrary functor to a unified type which is opaque.
+ * sigc::slot itself is a functor or, to be more precise, a closure. It contains
+ * a single, arbitrary functor (or closure) that is executed in operator()().
+ *
+ * The template arguments determine the function signature of operator()():
+ * - @e T_return The return type of operator()().
+ * - @e T_arg Argument types used in the definition of operator()().
+ *
+ * For instance, to declare a slot that returns void and takes two parameters
+ * of bool and int:
+ * @code
+ * sigc::slot<void(bool, int)> some_slot;
+ * @endcode
+ *
+ * Alternatively, you may use this syntax:
+ * @code
+ * sigc::slot<void, bool, int> some_slot;
+ * @endcode
+ *
+ * To use, simply assign the desired functor to the slot. If the functor
+ * is not compatible with the parameter list defined with the template
+ * arguments then compiler errors are triggered. When called, the slot
+ * will invoke the functor with minimal copies.
+ * block() and unblock() can be used to block the functor's invocation
+ * from operator()() temporarily.
+ *
+ * @ingroup slot
+ */
+template <class T_return, class... T_arg>
+class slot<T_return(T_arg...)>
+  : public slot_base
+{
+public:
+  using result_type = T_return;
+  //TODO: using arg_type_ = type_trait_take_t<T_arg>;
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+private:
+  using rep_type = internal::slot_rep;
+public:
+  using call_type = T_return (*)(rep_type*, type_trait_take_t<T_arg>...);
+#endif
+
+  /** Invoke the contained functor unless slot is in blocking state.
+   * @param _A_a Arguments to be passed on to the functor.
+   * @return The return value of the functor invocation.
+   */
+  inline T_return operator()(type_trait_take_t<T_arg>... _A_a) const
+    {
+      if (!empty() && !blocked())
+        return (reinterpret_cast<call_type>(slot_base::rep_->call_))(slot_base::rep_, _A_a...);
+      return T_return();
+    }
+
+  inline slot() {}
+
+  /** Constructs a slot from an arbitrary functor.
+   * @param _A_func The desired functor the new slot should be assigned to.
+   */
+  template <class T_functor>
+  slot(const T_functor& _A_func)
+    : slot_base(new internal::typed_slot_rep<T_functor>(_A_func))
+    {
+      //The slot_base:: is necessary to stop the HP-UX aCC compiler from being confused. murrayc.
+      slot_base::rep_->call_ = internal::slot_call<T_functor, T_return, T_arg...>::address();
+    }
+
+  /** Constructs a slot, copying an existing one.
+   * @param src The existing slot to copy.
+   */
+  slot(const slot& src)
+    : slot_base(src)
+    {}
+
+  /** Constructs a slot, moving an existing one.
+   * If @p src is connected to a parent (e.g. a signal), it is copied, not moved.
+   * @param src The existing slot to move or copy.
+   */
+  slot(slot&& src)
+    : slot_base(std::move(src))
+    {}
+
+  /** Overrides this slot, making a copy from another slot.
+   * @param src The slot from which to make a copy.
+   * @return @p this.
+   */
+  slot& operator=(const slot& src)
+  {
+    slot_base::operator=(src);
+    return *this;
+  }
+
+  /** Overrides this slot, making a move from another slot.
+   * If @p src is connected to a parent (e.g. a signal), it is copied, not moved.
+   * @param src The slot from which to move or copy.
+   * @return @p this.
+   */
+  slot& operator=(slot&& src)
+  {
+    slot_base::operator=(std::move(src));
+    return *this;
+  }
+};
+
+
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 //template specialization of visitor<>::do_visit_each<>(action, functor):
 /** Performs a functor on each of the targets of a functor.
diff --git a/tests/test_slot.cc b/tests/test_slot.cc
index 49c0226..40e55dc 100644
--- a/tests/test_slot.cc
+++ b/tests/test_slot.cc
@@ -50,6 +50,18 @@ void test_simple()
   util->check_result(result_stream, "foo(int 2)");
 }
 
+void test_std_function_style_syntax()
+{
+  // simple test
+  sigc::slot<void(int)> s1 = foo();
+  s1(1);
+  util->check_result(result_stream, "foo(int 1)");
+
+  s1 = foo();
+  s1(2);
+  util->check_result(result_stream, "foo(int 2)");
+}
+
 void test_implicit_conversion()
 {
   // test implicit conversion
@@ -100,6 +112,7 @@ int main(int argc, char* argv[])
     return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE;
 
   test_simple();
+  test_std_function_style_syntax();
   test_implicit_conversion();
   test_reference();
   test_operator_equals();


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