Fix Bug 1669 - ns-3 should support binding two and three (possibly more) arguments
authorVedran Miletić <rivanvx@gmail.com>
Sat, 25 May 2013 18:18:00 +0200
changeset 9816 e86da132e7e9
parent 9815 ffa2ab77b59b
child 9817 cfb7c304cf2d
Fix Bug 1669 - ns-3 should support binding two and three (possibly more) arguments
RELEASE_NOTES
src/core/model/callback.h
src/core/test/callback-test-suite.cc
--- a/RELEASE_NOTES	Sat May 25 14:48:30 2013 +0200
+++ b/RELEASE_NOTES	Sat May 25 18:18:00 2013 +0200
@@ -28,6 +28,7 @@
 - Bug 1662 - m_type not set for Ipv6OptionRouterAlertHeader
 - Bug 1678 - C++11 compliance problem with std::pair"
 - Bug 1683 - IPv6 autoconfigured don't use *infinite* lifetimes
+- Bug 1669 - ns-3 should support binding two and three (possibly more) arguments
 
 Known issues
 ------------
--- a/src/core/model/callback.h	Sat May 25 14:48:30 2013 +0200
+++ b/src/core/model/callback.h	Sat May 25 18:18:00 2013 +0200
@@ -319,6 +319,105 @@
   typename TypeTraits<TX>::ReferencedType m_a;
 };
 
+template <typename T, typename R, typename TX1, typename TX2, typename T1, typename T2, typename T3, typename T4,typename T5, typename T6, typename T7>
+class TwoBoundFunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,empty,empty> {
+public:
+  template <typename FUNCTOR, typename ARG1, typename ARG2>
+  TwoBoundFunctorCallbackImpl (FUNCTOR functor, ARG1 arg1, ARG2 arg2)
+    : m_functor (functor), m_a1 (arg1), m_a2 (arg2) {}
+  virtual ~TwoBoundFunctorCallbackImpl () {}
+  R operator() (void) {
+    return m_functor (m_a1,m_a2);
+  }
+  R operator() (T1 a1) {
+    return m_functor (m_a1,m_a2,a1);
+  }
+  R operator() (T1 a1,T2 a2) {
+    return m_functor (m_a1,m_a2,a1,a2);
+  }
+  R operator() (T1 a1,T2 a2,T3 a3) {
+    return m_functor (m_a1,m_a2,a1,a2,a3);
+  }
+  R operator() (T1 a1,T2 a2,T3 a3,T4 a4) {
+    return m_functor (m_a1,m_a2,a1,a2,a3,a4);
+  }
+  R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
+    return m_functor (m_a1,m_a2,a1,a2,a3,a4,a5);
+  }
+  R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6) {
+    return m_functor (m_a1,m_a2,a1,a2,a3,a4,a5,a6);
+  }
+  R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7) {
+    return m_functor (m_a1,m_a2,a1,a2,a3,a4,a5,a6,a7);
+  }
+  virtual bool IsEqual (Ptr<const CallbackImplBase> other) const {
+    TwoBoundFunctorCallbackImpl<T,R,TX1,TX2,T1,T2,T3,T4,T5,T6,T7> const *otherDerived = 
+      dynamic_cast<TwoBoundFunctorCallbackImpl<T,R,TX1,TX2,T1,T2,T3,T4,T5,T6,T7> const *> (PeekPointer (other));
+    if (otherDerived == 0)
+      {
+        return false;
+      }
+    else if (otherDerived->m_functor != m_functor ||
+             otherDerived->m_a1 != m_a1 || otherDerived->m_a2 != m_a2)
+      {
+        return false;
+      }
+    return true;
+  }
+private:
+  T m_functor;
+  typename TypeTraits<TX1>::ReferencedType m_a1;
+  typename TypeTraits<TX2>::ReferencedType m_a2;
+};
+
+template <typename T, typename R, typename TX1, typename TX2, typename TX3, typename T1, typename T2, typename T3, typename T4,typename T5, typename T6>
+class ThreeBoundFunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5,T6,empty,empty,empty> {
+public:
+  template <typename FUNCTOR, typename ARG1, typename ARG2, typename ARG3>
+  ThreeBoundFunctorCallbackImpl (FUNCTOR functor, ARG1 arg1, ARG2 arg2, ARG3 arg3)
+    : m_functor (functor), m_a1 (arg1), m_a2 (arg2), m_a3 (arg3) {}
+  virtual ~ThreeBoundFunctorCallbackImpl () {}
+  R operator() (void) {
+    return m_functor (m_a1,m_a2,m_a3);
+  }
+  R operator() (T1 a1) {
+    return m_functor (m_a1,m_a2,m_a3,a1);
+  }
+  R operator() (T1 a1,T2 a2) {
+    return m_functor (m_a1,m_a2,m_a3,a1,a2);
+  }
+  R operator() (T1 a1,T2 a2,T3 a3) {
+    return m_functor (m_a1,m_a2,m_a3,a1,a2,a3);
+  }
+  R operator() (T1 a1,T2 a2,T3 a3,T4 a4) {
+    return m_functor (m_a1,m_a2,m_a3,a1,a2,a3,a4);
+  }
+  R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
+    return m_functor (m_a1,m_a2,m_a3,a1,a2,a3,a4,a5);
+  }
+  R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6) {
+    return m_functor (m_a1,m_a2,m_a3,a1,a2,a3,a4,a5,a6);
+  }
+  virtual bool IsEqual (Ptr<const CallbackImplBase> other) const {
+    ThreeBoundFunctorCallbackImpl<T,R,TX1,TX2,TX3,T1,T2,T3,T4,T5,T6> const *otherDerived = 
+      dynamic_cast<ThreeBoundFunctorCallbackImpl<T,R,TX1,TX2,TX3,T1,T2,T3,T4,T5,T6> const *> (PeekPointer (other));
+    if (otherDerived == 0)
+      {
+        return false;
+      }
+    else if (otherDerived->m_functor != m_functor ||
+             otherDerived->m_a1 != m_a1 || otherDerived->m_a2 != m_a2 || otherDerived->m_a3 != m_a3)
+      {
+        return false;
+      }
+    return true;
+  }
+private:
+  T m_functor;
+  typename TypeTraits<TX1>::ReferencedType m_a1;
+  typename TypeTraits<TX2>::ReferencedType m_a2;
+  typename TypeTraits<TX3>::ReferencedType m_a3;
+};
 
 class CallbackBase {
 public:
@@ -396,6 +495,26 @@
     return Callback<R,T2,T3,T4,T5,T6,T7,T8,T9> (impl);
   }
 
+  template <typename TX1, typename TX2>
+  Callback<R,T3,T4,T5,T6,T7,T8,T9> TwoBind (TX1 a1, TX2 a2) {
+    Ptr<CallbackImpl<R,T3,T4,T5,T6,T7,T8,T9,empty,empty> > impl =
+      Ptr<CallbackImpl<R,T3,T4,T5,T6,T7,T8,T9,empty,empty> > (
+        new TwoBoundFunctorCallbackImpl<
+          Callback<R,T1,T2,T3,T4,T5,T6,T7,T8,T9>,
+          R,T1,T2,T3,T4,T5,T6,T7,T8,T9> (*this, a1, a2), false);
+    return Callback<R,T3,T4,T5,T6,T7,T8,T9> (impl);
+  }
+
+  template <typename TX1, typename TX2, typename TX3>
+  Callback<R,T4,T5,T6,T7,T8,T9> ThreeBind (TX1 a1, TX2 a2, TX3 a3) {
+    Ptr<CallbackImpl<R,T4,T5,T6,T7,T8,T9,empty,empty,empty> > impl =
+      Ptr<CallbackImpl<R,T4,T5,T6,T7,T8,T9,empty,empty,empty> > (
+        new ThreeBoundFunctorCallbackImpl<
+          Callback<R,T1,T2,T3,T4,T5,T6,T7,T8,T9>,
+          R,T1,T2,T3,T4,T5,T6,T7,T8,T9> (*this, a1, a2, a3), false);
+    return Callback<R,T4,T5,T6,T7,T8,T9> (impl);
+  }
+
   bool IsNull (void) const {
     return (DoPeekImpl () == 0) ? true : false;
   }
@@ -954,6 +1073,114 @@
     Create<BoundFunctorCallbackImpl<R (*)(TX,T1,T2,T3,T4,T5,T6,T7,T8),R,TX,T1,T2,T3,T4,T5,T6,T7,T8> > (fnPtr, a);
   return Callback<R,T1,T2,T3,T4,T5,T6,T7,T8> (impl);
 }
+
+template <typename R, typename TX1, typename TX2, typename ARG1, typename ARG2>
+Callback<R> MakeBoundCallback (R (*fnPtr)(TX1,TX2), ARG1 a1, ARG2 a2) {
+  Ptr<CallbackImpl<R,empty,empty,empty,empty,empty,empty,empty,empty,empty> > impl =
+    Create<TwoBoundFunctorCallbackImpl<R (*)(TX1,TX2),R,TX1,TX2,empty,empty,empty,empty,empty,empty,empty> >(fnPtr, a1, a2);
+  return Callback<R> (impl);
+}
+
+template <typename R, typename TX1, typename TX2, typename ARG1, typename ARG2,
+          typename T1>
+Callback<R,T1> MakeBoundCallback (R (*fnPtr)(TX1,TX2,T1), ARG1 a1, ARG2 a2) {
+  Ptr<CallbackImpl<R,T1,empty,empty,empty,empty,empty,empty,empty,empty> > impl =
+    Create<TwoBoundFunctorCallbackImpl<R (*)(TX1,TX2,T1),R,TX1,TX2,T1,empty,empty,empty,empty,empty,empty> > (fnPtr, a1, a2);
+  return Callback<R,T1> (impl);
+}
+template <typename R, typename TX1, typename TX2, typename ARG1, typename ARG2,
+          typename T1, typename T2>
+Callback<R,T1,T2> MakeBoundCallback (R (*fnPtr)(TX1,TX2,T1,T2), ARG1 a1, ARG2 a2) {
+  Ptr<CallbackImpl<R,T1,T2,empty,empty,empty,empty,empty,empty,empty> > impl =
+    Create<TwoBoundFunctorCallbackImpl<R (*)(TX1,TX2,T1,T2),R,TX1,TX2,T1,T2,empty,empty,empty,empty,empty> > (fnPtr, a1, a2);
+  return Callback<R,T1,T2> (impl);
+}
+template <typename R, typename TX1, typename TX2, typename ARG1, typename ARG2,
+          typename T1, typename T2,typename T3>
+Callback<R,T1,T2,T3> MakeBoundCallback (R (*fnPtr)(TX1,TX2,T1,T2,T3), ARG1 a1, ARG2 a2) {
+  Ptr<CallbackImpl<R,T1,T2,T3,empty,empty,empty,empty,empty,empty> > impl =
+    Create<TwoBoundFunctorCallbackImpl<R (*)(TX1,TX2,T1,T2,T3),R,TX1,TX2,T1,T2,T3,empty,empty,empty,empty> > (fnPtr, a1, a2);
+  return Callback<R,T1,T2,T3> (impl);
+}
+template <typename R, typename TX1, typename TX2, typename ARG1, typename ARG2,
+          typename T1, typename T2,typename T3,typename T4>
+Callback<R,T1,T2,T3,T4> MakeBoundCallback (R (*fnPtr)(TX1,TX2,T1,T2,T3,T4), ARG1 a1, ARG2 a2) {
+  Ptr<CallbackImpl<R,T1,T2,T3,T4,empty,empty,empty,empty,empty> > impl =
+    Create<TwoBoundFunctorCallbackImpl<R (*)(TX1,TX2,T1,T2,T3,T4),R,TX1,TX2,T1,T2,T3,T4,empty,empty,empty> > (fnPtr, a1, a2);
+  return Callback<R,T1,T2,T3,T4> (impl);
+}
+template <typename R, typename TX1, typename TX2, typename ARG1, typename ARG2,
+          typename T1, typename T2,typename T3,typename T4,typename T5>
+Callback<R,T1,T2,T3,T4,T5> MakeBoundCallback (R (*fnPtr)(TX1,TX2,T1,T2,T3,T4,T5), ARG1 a1, ARG2 a2) {
+  Ptr<CallbackImpl<R,T1,T2,T3,T4,T5,empty,empty,empty,empty> > impl =
+    Create<TwoBoundFunctorCallbackImpl<R (*)(TX1,TX2,T1,T2,T3,T4,T5),R,TX1,TX2,T1,T2,T3,T4,T5,empty,empty> > (fnPtr, a1, a2);
+  return Callback<R,T1,T2,T3,T4,T5> (impl);
+}
+template <typename R, typename TX1, typename TX2, typename ARG1, typename ARG2,
+          typename T1, typename T2,typename T3,typename T4,typename T5, typename T6>
+Callback<R,T1,T2,T3,T4,T5,T6> MakeBoundCallback (R (*fnPtr)(TX1,TX2,T1,T2,T3,T4,T5,T6), ARG1 a1, ARG2 a2) {
+  Ptr<CallbackImpl<R,T1,T2,T3,T4,T5,T6,empty,empty,empty> > impl =
+    Create<TwoBoundFunctorCallbackImpl<R (*)(TX1,TX2,T1,T2,T3,T4,T5,T6),R,TX1,TX2,T1,T2,T3,T4,T5,T6,empty> > (fnPtr, a1, a2);
+  return Callback<R,T1,T2,T3,T4,T5,T6> (impl);
+}
+template <typename R, typename TX1, typename TX2, typename ARG1, typename ARG2,
+          typename T1, typename T2,typename T3,typename T4,typename T5, typename T6, typename T7>
+Callback<R,T1,T2,T3,T4,T5,T6,T7> MakeBoundCallback (R (*fnPtr)(TX1,TX2,T1,T2,T3,T4,T5,T6,T7), ARG1 a1, ARG2 a2) {
+  Ptr<CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,empty,empty> > impl =
+    Create<TwoBoundFunctorCallbackImpl<R (*)(TX1,TX2,T1,T2,T3,T4,T5,T6,T7),R,TX1,TX2,T1,T2,T3,T4,T5,T6,T7> > (fnPtr, a1, a2);
+  return Callback<R,T1,T2,T3,T4,T5,T6,T7> (impl);
+}
+
+template <typename R, typename TX1, typename TX2, typename TX3, typename ARG1, typename ARG2, typename ARG3>
+Callback<R> MakeBoundCallback (R (*fnPtr)(TX1,TX2,TX3), ARG1 a1, ARG2 a2, ARG3 a3) {
+  Ptr<CallbackImpl<R,empty,empty,empty,empty,empty,empty,empty,empty,empty> > impl =
+    Create<ThreeBoundFunctorCallbackImpl<R (*)(TX1,TX2,TX3),R,TX1,TX2,TX3,empty,empty,empty,empty,empty,empty> >(fnPtr, a1, a2, a3);
+  return Callback<R> (impl);
+}
+
+template <typename R, typename TX1, typename TX2, typename TX3, typename ARG1, typename ARG2, typename ARG3,
+          typename T1>
+Callback<R,T1> MakeBoundCallback (R (*fnPtr)(TX1,TX2,TX3,T1), ARG1 a1, ARG2 a2, ARG3 a3) {
+  Ptr<CallbackImpl<R,T1,empty,empty,empty,empty,empty,empty,empty,empty> > impl =
+    Create<ThreeBoundFunctorCallbackImpl<R (*)(TX1,TX2,TX3,T1),R,TX1,TX2,TX3,T1,empty,empty,empty,empty,empty> > (fnPtr, a1, a2, a3);
+  return Callback<R,T1> (impl);
+}
+template <typename R, typename TX1, typename TX2, typename TX3, typename ARG1, typename ARG2, typename ARG3,
+          typename T1, typename T2>
+Callback<R,T1,T2> MakeBoundCallback (R (*fnPtr)(TX1,TX2,TX3,T1,T2), ARG1 a1, ARG2 a2, ARG3 a3) {
+  Ptr<CallbackImpl<R,T1,T2,empty,empty,empty,empty,empty,empty,empty> > impl =
+    Create<ThreeBoundFunctorCallbackImpl<R (*)(TX1,TX2,TX3,T1,T2),R,TX1,TX2,TX3,T1,T2,empty,empty,empty,empty> > (fnPtr, a1, a2, a3);
+  return Callback<R,T1,T2> (impl);
+}
+template <typename R, typename TX1, typename TX2, typename TX3, typename ARG1, typename ARG2, typename ARG3,
+          typename T1, typename T2,typename T3>
+Callback<R,T1,T2,T3> MakeBoundCallback (R (*fnPtr)(TX1,TX2,TX3,T1,T2,T3), ARG1 a1, ARG2 a2, ARG3 a3) {
+  Ptr<CallbackImpl<R,T1,T2,T3,empty,empty,empty,empty,empty,empty> > impl =
+    Create<ThreeBoundFunctorCallbackImpl<R (*)(TX1,TX2,TX3,T1,T2,T3),R,TX1,TX2,TX3,T1,T2,T3,empty,empty,empty> > (fnPtr, a1, a2, a3);
+  return Callback<R,T1,T2,T3> (impl);
+}
+template <typename R, typename TX1, typename TX2, typename TX3, typename ARG1, typename ARG2, typename ARG3,
+          typename T1, typename T2,typename T3,typename T4>
+Callback<R,T1,T2,T3,T4> MakeBoundCallback (R (*fnPtr)(TX1,TX2,TX3,T1,T2,T3,T4), ARG1 a1, ARG2 a2, ARG3 a3) {
+  Ptr<CallbackImpl<R,T1,T2,T3,T4,empty,empty,empty,empty,empty> > impl =
+    Create<ThreeBoundFunctorCallbackImpl<R (*)(TX1,TX2,TX3,T1,T2,T3,T4),R,TX1,TX2,TX3,T1,T2,T3,T4,empty,empty> > (fnPtr, a1, a2, a3);
+  return Callback<R,T1,T2,T3,T4> (impl);
+}
+template <typename R, typename TX1, typename TX2, typename TX3, typename ARG1, typename ARG2, typename ARG3,
+          typename T1, typename T2,typename T3,typename T4,typename T5>
+Callback<R,T1,T2,T3,T4,T5> MakeBoundCallback (R (*fnPtr)(TX1,TX2,TX3,T1,T2,T3,T4,T5), ARG1 a1, ARG2 a2, ARG3 a3) {
+  Ptr<CallbackImpl<R,T1,T2,T3,T4,T5,empty,empty,empty,empty> > impl =
+    Create<ThreeBoundFunctorCallbackImpl<R (*)(TX1,TX2,TX3,T1,T2,T3,T4,T5),R,TX1,TX2,TX3,T1,T2,T3,T4,T5,empty> > (fnPtr, a1, a2, a3);
+  return Callback<R,T1,T2,T3,T4,T5> (impl);
+}
+template <typename R, typename TX1, typename TX2, typename TX3, typename ARG1, typename ARG2, typename ARG3,
+          typename T1, typename T2,typename T3,typename T4,typename T5, typename T6>
+Callback<R,T1,T2,T3,T4,T5,T6> MakeBoundCallback (R (*fnPtr)(TX1,TX2,TX3,T1,T2,T3,T4,T5,T6), ARG1 a1, ARG2 a2, ARG3 a3) {
+  Ptr<CallbackImpl<R,T1,T2,T3,T4,T5,T6,empty,empty,empty> > impl =
+    Create<ThreeBoundFunctorCallbackImpl<R (*)(TX1,TX2,TX3,T1,T2,T3,T4,T5,T6),R,TX1,TX2,TX3,T1,T2,T3,T4,T5,T6> > (fnPtr, a1, a2, a3);
+  return Callback<R,T1,T2,T3,T4,T5,T6> (impl);
+}
+
 } // namespace ns3
 
 namespace ns3 {
--- a/src/core/test/callback-test-suite.cc	Sat May 25 14:48:30 2013 +0200
+++ b/src/core/test/callback-test-suite.cc	Sat May 25 18:18:00 2013 +0200
@@ -300,6 +300,24 @@
 static bool *gMakeBoundCallbackTest2;
 static bool *gMakeBoundCallbackTest3a;
 static int gMakeBoundCallbackTest3b;
+static int gMakeBoundCallbackTest4a;
+static int gMakeBoundCallbackTest4b;
+static int gMakeBoundCallbackTest5a;
+static int gMakeBoundCallbackTest5b;
+static int gMakeBoundCallbackTest5c;
+static int gMakeBoundCallbackTest6a;
+static int gMakeBoundCallbackTest6b;
+static int gMakeBoundCallbackTest6c;
+static int gMakeBoundCallbackTest7a;
+static int gMakeBoundCallbackTest7b;
+static int gMakeBoundCallbackTest7c;
+static int gMakeBoundCallbackTest8a;
+static int gMakeBoundCallbackTest8b;
+static int gMakeBoundCallbackTest8c;
+static int gMakeBoundCallbackTest9a;
+static int gMakeBoundCallbackTest9b;
+static int gMakeBoundCallbackTest9c;
+static int gMakeBoundCallbackTest9d;
 
 void 
 MakeBoundCallbackTarget1 (int a)
@@ -321,6 +339,57 @@
   return 1234;
 }
 
+void
+MakeBoundCallbackTarget4 (int a, int b)
+{
+  gMakeBoundCallbackTest4a = a;
+  gMakeBoundCallbackTest4b = b;
+}
+
+int
+MakeBoundCallbackTarget5 (int a, int b)
+{
+  gMakeBoundCallbackTest5a = a;
+  gMakeBoundCallbackTest5b = b;
+  return 1234;
+}
+
+int
+MakeBoundCallbackTarget6 (int a, int b, int c)
+{
+  gMakeBoundCallbackTest6a = a;
+  gMakeBoundCallbackTest6b = b;
+  gMakeBoundCallbackTest6c = c;
+  return 1234;
+}
+
+void
+MakeBoundCallbackTarget7 (int a, int b, int c)
+{
+  gMakeBoundCallbackTest7a = a;
+  gMakeBoundCallbackTest7b = b;
+  gMakeBoundCallbackTest7c = c;
+}
+
+int
+MakeBoundCallbackTarget8 (int a, int b, int c)
+{
+  gMakeBoundCallbackTest8a = a;
+  gMakeBoundCallbackTest8b = b;
+  gMakeBoundCallbackTest8c = c;
+  return 1234;
+}
+
+int
+MakeBoundCallbackTarget9 (int a, int b, int c, int d)
+{
+  gMakeBoundCallbackTest9a = a;
+  gMakeBoundCallbackTest9b = b;
+  gMakeBoundCallbackTest9c = c;
+  gMakeBoundCallbackTest9d = d;
+  return 1234;
+}
+
 MakeBoundCallbackTestCase::MakeBoundCallbackTestCase ()
   : TestCase ("Check MakeBoundCallback() mechanism")
 {
@@ -333,6 +402,24 @@
   gMakeBoundCallbackTest2 = 0;
   gMakeBoundCallbackTest3a = 0;
   gMakeBoundCallbackTest3b = 0;
+  gMakeBoundCallbackTest4a = 0;
+  gMakeBoundCallbackTest4b = 0;
+  gMakeBoundCallbackTest5a = 0;
+  gMakeBoundCallbackTest5b = 0;
+  gMakeBoundCallbackTest5c = 0;
+  gMakeBoundCallbackTest6a = 0;
+  gMakeBoundCallbackTest6b = 0;
+  gMakeBoundCallbackTest6c = 0;
+  gMakeBoundCallbackTest7a = 0;
+  gMakeBoundCallbackTest7b = 0;
+  gMakeBoundCallbackTest7c = 0;
+  gMakeBoundCallbackTest8a = 0;
+  gMakeBoundCallbackTest8b = 0;
+  gMakeBoundCallbackTest8c = 0;
+  gMakeBoundCallbackTest9a = 0;
+  gMakeBoundCallbackTest9b = 0;
+  gMakeBoundCallbackTest9c = 0;
+  gMakeBoundCallbackTest9d = 0;
 }
 
 void
@@ -376,6 +463,51 @@
   NS_TEST_ASSERT_MSG_EQ (result, 1234, "Return value of callback not correct");
   NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest3a, &a, "Callback did not fire or binding not correct");
   NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest3b, 2468, "Callback did not fire or argument not correct");
+
+  //
+  // Test the TwoBound variant
+  //
+  Callback<void> target4 = MakeBoundCallback (&MakeBoundCallbackTarget4, 3456, 5678);
+  target4 ();
+  NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest4a, 3456, "Callback did not fire or binding not correct");
+  NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest4b, 5678, "Callback did not fire or binding not correct");
+
+  Callback<int> target5 = MakeBoundCallback (&MakeBoundCallbackTarget5, 3456, 5678);
+  int resultTwoA = target5 ();
+  NS_TEST_ASSERT_MSG_EQ (resultTwoA, 1234, "Return value of callback not correct");
+  NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest5a, 3456, "Callback did not fire or binding not correct");
+  NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest5b, 5678, "Callback did not fire or binding not correct");
+
+  Callback<int, int> target6 = MakeBoundCallback (&MakeBoundCallbackTarget6, 3456, 5678);
+  int resultTwoB = target6 (6789);
+  NS_TEST_ASSERT_MSG_EQ (resultTwoB, 1234, "Return value of callback not correct");
+  NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest6a, 3456, "Callback did not fire or binding not correct");
+  NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest6b, 5678, "Callback did not fire or binding not correct");
+  NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest6c, 6789, "Callback did not fire or argument not correct");
+
+  //
+  // Test the ThreeBound variant
+  //
+  Callback<void> target7 = MakeBoundCallback (&MakeBoundCallbackTarget7, 2345, 3456, 4567);
+  target7 ();
+  NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest7a, 2345, "Callback did not fire or binding not correct");
+  NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest7b, 3456, "Callback did not fire or binding not correct");
+  NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest7c, 4567, "Callback did not fire or binding not correct");
+
+  Callback<int> target8 = MakeBoundCallback (&MakeBoundCallbackTarget8, 2345, 3456, 4567);
+  int resultThreeA = target8 ();
+  NS_TEST_ASSERT_MSG_EQ (resultThreeA, 1234, "Return value of callback not correct");
+  NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest8a, 2345, "Callback did not fire or binding not correct");
+  NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest8b, 3456, "Callback did not fire or binding not correct");
+  NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest8c, 4567, "Callback did not fire or binding not correct");
+
+  Callback<int, int> target9 = MakeBoundCallback (&MakeBoundCallbackTarget9, 2345, 3456, 4567);
+  int resultThreeB = target9 (5678);
+  NS_TEST_ASSERT_MSG_EQ (resultThreeB, 1234, "Return value of callback not correct");
+  NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest9a, 2345, "Callback did not fire or binding not correct");
+  NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest9b, 3456, "Callback did not fire or binding not correct");
+  NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest9c, 4567, "Callback did not fire or binding not correct");
+  NS_TEST_ASSERT_MSG_EQ (gMakeBoundCallbackTest9d, 5678, "Callback did not fire or binding not correct");
 }
 
 // ===========================================================================