+ result_type operator()() const
+ {
+ return Caller::call(firstBound);
+ }
+ FirstBound getBound() const
+ {
+ return firstBound;
+ }
+ static result_type thunk(void* environment)
+ {
+ return Caller::call(ConvertFromOpaque<FirstBound>::apply(environment));
+ }
+ void* getEnvironment() const
+ {
+ return convertToOpaque(firstBound);
+ }
+};
+
+template<typename Caller>
+class BindFirstOpaque1
+{
+ typedef typename Caller::first_argument_type FirstBound;
+ FirstBound firstBound;
+public:
+ typedef typename Caller::second_argument_type first_argument_type;
+ typedef typename Caller::result_type result_type;
+ explicit BindFirstOpaque1(FirstBound firstBound) : firstBound(firstBound)
+ {
+ }
+ result_type operator()(first_argument_type a1) const
+ {
+ return Caller::call(firstBound, a1);
+ }
+ FirstBound getBound() const
+ {
+ return firstBound;
+ }
+ static result_type thunk(void* environment, first_argument_type a1)
+ {
+ return Caller::call(ConvertFromOpaque<FirstBound>::apply(environment), a1);
+ }
+ void* getEnvironment() const
+ {
+ return convertToOpaque(firstBound);
+ }
+};
+
+template<typename Caller>
+class BindFirstOpaque2
+{
+ typedef typename Caller::first_argument_type FirstBound;
+ FirstBound firstBound;
+public:
+ typedef typename Caller::second_argument_type first_argument_type;
+ typedef typename Caller::third_argument_type second_argument_type;
+ typedef typename Caller::result_type result_type;
+ explicit BindFirstOpaque2(FirstBound firstBound) : firstBound(firstBound)
+ {
+ }
+ result_type operator()(first_argument_type a1, second_argument_type a2) const
+ {
+ return Caller::call(firstBound, a1, a2);
+ }
+ FirstBound getBound() const
+ {
+ return firstBound;
+ }
+ static result_type thunk(void* environment, first_argument_type a1, second_argument_type a2)
+ {
+ return Caller::call(ConvertFromOpaque<FirstBound>::apply(environment), a1, a2);
+ }
+ void* getEnvironment() const
+ {
+ return convertToOpaque(firstBound);
+ }
+};
+
+template<typename Caller>
+class BindFirstOpaque3
+{
+ typedef typename Caller::first_argument_type FirstBound;
+ FirstBound firstBound;
+public:
+ typedef typename Caller::second_argument_type first_argument_type;
+ typedef typename Caller::third_argument_type second_argument_type;
+ typedef typename Caller::fourth_argument_type third_argument_type;
+ typedef typename Caller::result_type result_type;
+ explicit BindFirstOpaque3(FirstBound firstBound) : firstBound(firstBound)
+ {
+ }
+ result_type operator()(first_argument_type a1, second_argument_type a2, third_argument_type a3) const
+ {
+ return Caller::call(firstBound, a1, a2, a3);
+ }
+ FirstBound getBound() const
+ {
+ return firstBound;
+ }
+ static result_type thunk(void* environment, first_argument_type a1, second_argument_type a2, third_argument_type a3)
+ {
+ return Caller::call(ConvertFromOpaque<FirstBound>::apply(environment), a1, a2, a3);
+ }
+ void* getEnvironment() const
+ {
+ return convertToOpaque(firstBound);
+ }
+};
+
+template<typename Thunk_>
+class CallbackBase
+{
+ void* m_environment;
+ Thunk_ m_thunk;
+public:
+ typedef Thunk_ Thunk;
+ CallbackBase(void* environment, Thunk function) : m_environment(environment), m_thunk(function)