[libsigcplusplus/variadic_mem_fun3: 120/148] limit_reference.h.m4: Make *_limit_reference template aliases of a limit_reference_base.



commit 53610843e1f716de5dc98c6a34837b90c3103591
Author: Murray Cumming <murrayc murrayc com>
Date:   Fri Mar 4 14:43:49 2016 +0100

    limit_reference.h.m4: Make *_limit_reference template aliases of a limit_reference_base.
    
    And have just one visitor specialization, using the base class.
    As for *_mem_functor. This avoids the repetition.

 sigc++/macros/limit_reference.h.m4 |   74 ++++++++++++++++++++++++------------
 1 files changed, 50 insertions(+), 24 deletions(-)
---
diff --git a/sigc++/macros/limit_reference.h.m4 b/sigc++/macros/limit_reference.h.m4
index 679a86c..c8feabd 100644
--- a/sigc++/macros/limit_reference.h.m4
+++ b/sigc++/macros/limit_reference.h.m4
@@ -39,16 +39,50 @@ define([LIMIT_REFERENCE],[dnl
  *
  * - @e T_type The type of the reference.
  */
-template <class T_type,
+template <class T_type>
+using [$1]limit_reference = limit_reference_base<[$2]T_type, [$3]T_type, [$2]trackable>;
+])
+
+divert(0)
+
+_FIREWALL([LIMIT_REFERENCE])
+
+#include <sigc++/visit_each.h>
+#include <sigc++/type_traits.h>
+#include <sigc++/trackable.h>
+
+namespace sigc {
+
+/** A limit_reference_base<Foo> object stores a reference (Foo&), but make sure that,
+ * if Foo inherits from sigc::trackable, then visit_each<>() will "limit" itself to the
+ * sigc::trackable reference instead of the derived reference. This avoids use of
+ * a reference to the derived type when the derived destructor has run. That can be
+ * a problem when using virtual inheritance.
+ *
+ * If Foo inherits from trackable then both the derived reference and the
+ * sigc::trackable reference are stored, so we can later retrieve the sigc::trackable
+ * reference without doing an implicit conversion. To retrieve the derived reference
+ * (so that you invoke methods or members of it), use invoke(). To retrieve the trackable
+ * reference (so that you can call visit_each() on it), you use visit().
+ *
+ * If Foo does not inherit from sigc::trackable then invoke() and visit() just return the
+ * derived reference.
+ *
+ * This is used for bound (sigc::bind) slot parameters (via bound_argument), bound return values,
+ * and, with mem_fun(), the reference to the handling object.
+ *
+ * - @e T_type The type of the reference.
+ */
+template <class T_type, class T_type_invoke_result, class T_trackable,
           bool I_derives_trackable =
-            std::is_base_of<trackable, T_type>::value>
-class [$1]limit_reference
+            std::is_base_of<trackable, std::decay_t<T_type>>::value>
+class limit_reference_base
 {
 public:
   /** Constructor.
    * @param _A_target The reference to limit.
    */
-  [$1]limit_reference([$2]T_type& _A_target)
+  limit_reference_base(T_type& _A_target)
     : visited(_A_target)
     {}
 
@@ -63,26 +97,26 @@ public:
    * This is always a reference to the derived instance.
    * @return The reference.
    */
-  inline [$3]T_type& invoke() const
+  inline T_type_invoke_result& invoke() const
     { return visited; }
 
 private:
   /** The reference.
    */
-  [$2]T_type& visited;
+  T_type& visited;
 };
 
-/** [$1]limit_reference object for a class that derives from trackable.
+/** limit_reference_base object for a class that derives from trackable.
  * - @e T_type The type of the reference.
  */
-template <class T_type>
-class [$1]limit_reference<T_type, true>
+template <class T_type, class T_type_invoke_result, class T_trackable>
+class limit_reference_base<T_type, T_type_invoke_result, T_trackable, true>
 {
 public:
   /** Constructor.
    * @param _A_target The reference to limit.
    */
-  [$1]limit_reference([$2]T_type& _A_target)
+  limit_reference_base(T_type& _A_target)
     : visited(_A_target),
       invoked(_A_target)
     {}
@@ -98,17 +132,17 @@ public:
    * This is always a reference to the derived instance.
    * @return The reference.
    */
-  inline [$3]T_type& invoke() const
+  inline T_type_invoke_result& invoke() const
     { return invoked; }
 
 private:
   /** The trackable reference.
    */
-  [$2]trackable& visited;
+  T_trackable& visited;
 
   /** The reference.
    */
-  [$2]T_type& invoked;
+  T_type& invoked;
 };
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
@@ -120,28 +154,20 @@ private:
  * @param _A_action The functor to invoke.
  * @param _A_target The visited instance.
  */
-template <class T_type, bool I_derives_trackable>
-struct visitor<[$1]limit_reference<T_type, I_derives_trackable> >
+template <class T_type, class T_type_invoke_result, class T_trackable>
+struct visitor<limit_reference_base<T_type, T_type_invoke_result, T_trackable> >
 {
   template <class T_action>
   static void do_visit_each(const T_action& _A_action,
-                            const [$1]limit_reference<T_type, I_derives_trackable>& _A_target)
+                            const limit_reference_base<T_type, T_type_invoke_result, T_trackable>& _A_target)
   {
     sigc::visit_each(_A_action, _A_target.visit());
   }
 };
 #endif // DOXYGEN_SHOULD_SKIP_THIS
-])
-
-divert(0)
 
-_FIREWALL([LIMIT_REFERENCE])
 
-#include <sigc++/visit_each.h>
-#include <sigc++/type_traits.h>
-#include <sigc++/trackable.h>
 
-namespace sigc {
 
 LIMIT_REFERENCE([],[],[])dnl
 


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