Boost logo

Boost :

From: Jesse Jones (jejones_at_[hidden])
Date: 2000-11-16 21:26:54


>> Or, alternatively, you can assign a function with two arguments to a
>> callback with one if the second argument has a default value.
>>
>I don't know how you are going to do this, the default value doesn't appear
>to travel with the function. If you know how, please let me know.

You have to treat the function as a black box (ie you can't expload it and
pick out the argument types). I've appended a stripped down version of the
code I use below. I think it supports all the requirements mentioned so far
except allowing a function that returns a value to be assigned to a
callback that returns void. I had a nice meta-programming fix for this, but
I couldn't get it past CW 5.3 so in the real code I specialized
FunctorCallback1 and MethodCallback1 for void RETURN_TYPE's.

template <class RETURN_TYPE, class ARG1>
class Callback1 {

public:
   typedef RETURN_TYPE result_type;
   typedef ARG1 argument_type;

public:
                  ~Callback1() {if (mCallback != nil)
mCallback->RemoveReference();}

                  Callback1() : mCallback(nil) {}

                  template <class FUNCTION>
                  Callback1(FUNCTION function) : mCallback(new
Internals::FunctorCallback1<FUNCTION, RETURN_TYPE, ARG1>(function)) {}

                  template <class OBJECT, class METHOD>
                  Callback1(OBJECT* object, METHOD method) : mCallback(new
Internals::MethodCallback1<OBJECT, METHOD, RETURN_TYPE, ARG1>(object,
method)) {}

   // plus more stuff like copy ctor, assignment operator, operator==, etc

public:
         RETURN_TYPE operator()(ARG1 arg1) const {return
mCallback->Call(arg1);}

private:
   Internals::BaseCallback1<RETURN_TYPE, ARG1>* mCallback;
};

namespace Internals {
   template <class RETURN_TYPE, class ARG1>
   class BaseCallback1 : public ReferenceCountedMixin {

   public:
      virtual ~BaseCallback1() {}

                     BaseCallback1() {}

   public:
      virtual RETURN_TYPE Call(ARG1 arg1) const = 0;
   };

   template <class FUNCTOR, class RETURN_TYPE, class ARG1>
   class FunctorCallback1 : public BaseCallback1<RETURN_TYPE, ARG1> {

   public:
      FunctorCallback1(FUNCTOR functor) : mFunctor(functor) {}

      virtual RETURN_TYPE Call(ARG1 arg1) const {return mFunctor(arg1);}

   private:
      FUNCTOR mFunctor;
   };

   template <class OBJECT, class METHOD, class RETURN_TYPE, class ARG1>
   class MethodCallback1 : public BaseCallback1<RETURN_TYPE, ARG1> {

   public:
                     MethodCallback1(OBJECT* object, METHOD method)
{ASSERT(object != nil); ASSERT(method != nil); mObject = object; mMethod =
method;}

      virtual RETURN_TYPE Call(ARG1 arg1) const {return
(mObject->*mMethod)(arg1);}

   private:
      OBJECT* mObject;
      METHOD mMethod;
   };
} // namespace Internals

  -- Jesse


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk