]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/include/smobs.hh
Issue 4400: Rework LY_DECLARE_SMOB_PROC to declare a member function
[lilypond.git] / lily / include / smobs.hh
index 7097bb3d48c6605b4a08ff769d54bc80be9e0651..ee6af16162be9da50d33da46753708a99d22718d 100644 (file)
@@ -185,6 +185,7 @@ private:
   static SCM equal_p (SCM, SCM);
   int print_smob (SCM, scm_print_state *);
   static int print_trampoline (SCM, SCM, scm_print_state *);
+  static void smob_proc_init (scm_t_bits) { };
 
   // type_p_name_ can be overriden in the Super class with a static
   // const char [] string.  This requires both a declaration in the
@@ -200,25 +201,41 @@ private:
   static const int type_p_name_ = 0;
 
   // LY_DECLARE_SMOB_PROC is used in the Super class definition for
-  // making a smob callable like a function.  Declaration has to be
-  // public.  It may be either be completed with a semicolon in which
-  // case a definition of the member function smob_proc has to be done
-  // outside of the class body, or the semicolon is left off and an
-  // inline function body is added immediately below.  It would be
-  // nice if this were a non-static member function but it would seem
-  // tricky to do the required trampolining for unsmobbing the first
-  // argument of the callback and using it as a this pointer.
-#define LY_DECLARE_SMOB_PROC(REQ, OPT, VAR, ARGLIST)                    \
-  static const int smob_proc_signature_ = ((REQ)<<8)|((OPT)<<4)|(VAR);  \
-  static SCM smob_proc ARGLIST
-
-  // a separate LY_DEFINE_SMOB_PROC seems sort of pointless as it
-  // would just result in SCM CLASS::smob_proc ARGLIST
-  //
-  // The default case without function functionality is recognized by
-  // smob_proc_signature being -1.
-  static const int smob_proc = 0;
-  static const int smob_proc_signature_ = -1;
+  // making a smob callable like a function.  Its first argument is a
+  // function member pointer constant, to a function taking the
+  // correct number of SCM arguments and returning SCM.  The function
+  // itself has to be defined separately.
+
+#define LY_DECLARE_SMOB_PROC(PMF, REQ, OPT, VAR)                        \
+  static void smob_proc_init (scm_t_bits smob_tag)                      \
+  {                                                                     \
+    scm_set_smob_apply (smob_tag,                                       \
+                        (scm_t_subr)smob_trampoline<PMF>,               \
+                        REQ, OPT, VAR);                                 \
+  }
+
+  // Well, function template argument packs are a C++11 feature.  So
+  // we just define a bunch of trampolines manually.
+  template <SCM (Super::*pmf)(void)>
+  static SCM smob_trampoline (SCM self)
+  {
+    return (Super::unchecked_unsmob (self)->*pmf)();
+  }
+  template <SCM (Super::*pmf)(SCM)>
+  static SCM smob_trampoline (SCM self, SCM arg1)
+  {
+    return (Super::unchecked_unsmob (self)->*pmf)(arg1);
+  }
+  template <SCM (Super::*pmf)(SCM, SCM)>
+  static SCM smob_trampoline (SCM self, SCM arg1, SCM arg2)
+  {
+    return (Super::unchecked_unsmob (self)->*pmf)(arg1, arg2);
+  }
+  template <SCM (Super::*pmf)(SCM, SCM, SCM)>
+  static SCM smob_trampoline (SCM self, SCM arg1, SCM arg2, SCM arg3)
+  {
+    return (Super::unchecked_unsmob (self)->*pmf)(arg1, arg2, arg3);
+  }
 
 public:
   static bool is_smob (SCM s)