在C++中实现delegate

delegate.h
#ifndef WAN_DELEGATE_H
#define WAN_DELEGATE_H
  
/**
 * @author Kevin Wan <wanjunfeng@gmail.com>
 * @date   06/30/2005
 * Copyright (C) Kevin Wan
 */
#include "threadingmodel.h"
  
namespace wan
{
namespace local
{
template <typename> class ICallback;
template <typename> class NativeCallback;
template <typename, typename> class MemberCallback;
} // namespace local
template <typename, typename LockType = void> class delegate;
#define DELEGATE_GENERATOR(TEMPLATE_LIST, TYPE_LIST, TYPE_PARAM_LIST, PARAM_LIST) \
namespace local \
{ \
template <typename ReturnType TEMPLATE_LIST> \
class ICallback<ReturnType(TYPE_LIST)> \
{ \
    typedef ICallback<ReturnType(TYPE_LIST)> SelfType; \
\
public: \
    virtual ~ICallback() {} \
\
    virtual ReturnType invoke(TYPE_LIST) const = 0; \
    virtual bool equals(const SelfType* pDelegate) const = 0; \
    virtual SelfType* clone() const = 0; \
}; \
\
template <typename ReturnType TEMPLATE_LIST> \
class NativeCallback<ReturnType(TYPE_LIST)> \
    : public ICallback<ReturnType(TYPE_LIST)> \
{ \
    typedef ICallback<ReturnType(TYPE_LIST)> SuperType; \
    typedef NativeCallback<ReturnType(TYPE_LIST)> SelfType; \
    typedef ReturnType (*FunctionPtr)(TYPE_LIST); \
\
public: \
    explicit NativeCallback(FunctionPtr ptr) \
        : m_handler(ptr) \
    { \
    } \
\
    NativeCallback(const SelfType& rhs) \
        : ICallback<ReturnType(TYPE_LIST)>(rhs) \
        , m_handler(rhs.m_handler) \
    { \
    } \
\
    ReturnType invoke(TYPE_PARAM_LIST) const \
    { \
        return (*m_handler)(PARAM_LIST); \
    } \
\
    bool equals(const SuperType* pDelegate) const \
    { \
        const SelfType* pRhs = dynamic_cast<const SelfType*>(pDelegate); \
        if (pRhs == 0) return false; \
        if (m_handler == pRhs->m_handler) return true; \
        return false; \
    } \
\
    SelfType* clone() const \
    { \
        return new SelfType(*this); \
    } \
\
private: \
    FunctionPtr m_handler; \
}; \
\
template <typename ObjectType, typename ReturnType TEMPLATE_LIST> \
class MemberCallback<ObjectType, ReturnType(TYPE_LIST)> \
    : public ICallback<ReturnType(TYPE_LIST)> \
{ \
    typedef ICallback<ReturnType(TYPE_LIST)> SuperType; \
    typedef MemberCallback<ObjectType, ReturnType(TYPE_LIST)> SelfType; \
    typedef ReturnType (ObjectType::*FunctionPtr)(TYPE_LIST); \
    typedef ReturnType (ObjectType::*ConstFunctionPtr)(TYPE_LIST) const; \
\
    enum { CONST_POINTER, NEED_DELETE, DONT_DELETE }; \
    struct ObjectManager \
    { \
        bool equals(const ObjectManager& rhs) \
        { \
            return object.pObject == rhs.object.pObject; \
        } \
\
        union { ObjectType* pObject; const ObjectType* pConstObject; } object; \
        int                 property; \
        int                 refCount; \
    }; \
\
public: \
    MemberCallback(ObjectType* t, FunctionPtr ptr, bool needDelete = false) \
        : m_isConstMemFunc(false) \
    { \
        m_pObjectManager = new ObjectManager(); \
        m_pObjectManager->object.pObject = t; \
        m_pObjectManager->property = needDelete ? NEED_DELETE : DONT_DELETE; \
        m_pObjectManager->refCount = 0; \
        m_handler.ptr = ptr; \
        incrementRefCount(); \
    } \
\
    MemberCallback(ObjectType* t, ConstFunctionPtr ptr, bool needDelete = false) \
        : m_isConstMemFunc(true) \
    { \
        m_pObjectManager = new ObjectManager(); \
        m_pObjectManager->object.pObject = t; \
        m_pObjectManager->property = needDelete ? NEED_DELETE : DONT_DELETE; \
        m_pObjectManager->refCount = 0; \
        m_handler.constPtr = ptr; \
        incrementRefCount(); \
    } \
\
    MemberCallback(const ObjectType* t, ConstFunctionPtr ptr) \
        : m_isConstMemFunc(true) \
    { \
        m_pObjectManager = new ObjectManager(); \
        m_pObjectManager->object.pConstObject = t; \
        m_pObjectManager->property = CONST_POINTER; \
        m_pObjectManager->refCount = 0; \
        m_handler.constPtr = ptr; \
        incrementRefCount(); \
    } \
\
    MemberCallback(const SelfType& rhs) \
        : ICallback<ReturnType(TYPE_LIST)>(rhs) \
        , m_pObjectManager(rhs.m_pObjectManager) \
        , m_handler(rhs.m_handler) \
        , m_isConstMemFunc(rhs.m_isConstMemFunc) \
    { \
        incrementRefCount(); \
    } \
\
    virtual ~MemberCallback() \
    { \
        decrementRefCount(); \
    } \
\
    MemberCallback& operator=(const SelfType& rhs) \
    { \
        if (this == &rhs) \
            return *this; \
        decrementRefCount(); \
        m_pObjectManager = rhs.m_pObjectManager; \
        m_handler = rhs.m_handler; \
        m_isConstMemFunc = rhs.m_isConstMemFunc; \
        incrementRefCount(); \
        return *this; \
    } \
\
    ReturnType invoke(TYPE_PARAM_LIST) const \
    { \
        if (m_isConstMemFunc) \
        { \
            if (m_pObjectManager->property == CONST_POINTER) \
                return (m_pObjectManager->object.pConstObject->*(m_handler.constPtr))(PARAM_LIST); \
            return (m_pObjectManager->object.pObject->*(m_handler.constPtr))(PARAM_LIST); \
        } \
        return (m_pObjectManager->object.pObject->*(m_handler.ptr))(PARAM_LIST); \
    } \
\
    bool equals(const SuperType* pDelegate) const \
    { \
        const SelfType* pRhs = dynamic_cast<const SelfType*>(pDelegate); \
        if (pRhs == 0) return false; \
        if (m_pObjectManager->equals(*pRhs->m_pObjectManager) \
                && m_isConstMemFunc == pRhs->m_isConstMemFunc \
                && m_handler.ptr == pRhs->m_handler.ptr) \
            return true; \
        return false; \
    } \
\
    SelfType* clone() const \
    { \
        return new SelfType(*this); \
    } \
\
private: \
    void incrementRefCount() \
    { \
        ++m_pObjectManager->refCount; \
    } \
\
    void decrementRefCount() \
    { \
        if (--m_pObjectManager->refCount == 0) \
        { \
            if (m_pObjectManager->property == NEED_DELETE) \
                delete m_pObjectManager->object.pObject; \
\
            delete m_pObjectManager; \
        } \
    } \
\
private: \
    ObjectManager*  m_pObjectManager; \
    union { FunctionPtr ptr; ConstFunctionPtr constPtr; } m_handler; \
    bool            m_isConstMemFunc; \
}; \
} /* namespace local */ \
\
template <typename ReturnType TEMPLATE_LIST, typename LockType> \
class delegate<ReturnType(TYPE_LIST), LockType> \
    : public local::ICallback<ReturnType(TYPE_LIST)> \
    , public ThreadingModel<LockType> \
{ \
    typedef local::ICallback<ReturnType(TYPE_LIST)> SuperType; \
    typedef delegate<ReturnType(TYPE_LIST), LockType> SelfType; \
    typedef ThreadingModel<LockType> ThreadingModelType; \
    struct CallbackHolder \
    { \
        SuperType*      instance; \
        CallbackHolder* prev; \
        ReturnType call(TYPE_PARAM_LIST) \
        { \
            if (prev != 0) prev->call(PARAM_LIST); \
            return instance->invoke(PARAM_LIST); \
        } \
    }; \
\
public: \
    delegate() : m_pHolder(0) {} \
\
    explicit delegate(ReturnType (*ptr)(TYPE_LIST)) \
        : m_pHolder(0) \
    { \
        this->add(ptr); \
    } \
\
    template <typename ObjectType> \
    delegate(const ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST) const) \
        : m_pHolder(0) \
    { \
        this->add(t, ptr); \
    } \
\
    template <typename ObjectType> \
    delegate(ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST), \
            bool needDelete = false) \
        : m_pHolder(0) \
    { \
        this->add(t, ptr, needDelete); \
    } \
\
    template <typename ObjectType> \
    delegate(ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST) const, \
            bool needDelete = false) \
        : m_pHolder(0) \
    { \
        this->add(t, ptr, needDelete); \
    } \
\
    template <typename FunctorType> \
    explicit delegate(const FunctorType* pFunctor) \
        : m_pHolder(0) \
    { \
        this->add(pFunctor); \
    } \
\
    template <typename FunctorType> \
    explicit delegate(FunctorType* pFunctor, bool needDelete = false) \
        : m_pHolder(0) \
    { \
        this->add(pFunctor, needDelete); \
    } \
\
    delegate(const SelfType& rhs) \
        : local::ICallback<ReturnType(TYPE_LIST)>(rhs) \
        , ThreadingModelType() \
    { \
        copyFrom(rhs); \
    } \
\
    SelfType& operator=(const SelfType& rhs) \
    { \
        if (this == &rhs) \
            return *this; \
        this->release(); \
        copyFrom(rhs); \
        return *this; \
    } \
\
    ~delegate() \
    { \
        release(); \
    } \
\
    void release() \
    { \
        typename ThreadingModelType::Lock guard(*this); \
        CallbackHolder* ptr = m_pHolder; \
        while (ptr != 0) \
        { \
            CallbackHolder* prev = ptr->prev; \
            delete ptr->instance; \
            delete ptr; \
            ptr = prev; \
        } \
        m_pHolder = 0; \
    } \
\
    ReturnType operator()(TYPE_PARAM_LIST) \
    { \
        return this->invoke(PARAM_LIST); \
    } \
\
    ReturnType invoke(TYPE_PARAM_LIST) const \
    { \
        typename ThreadingModelType::Lock guard(*this); \
        if (m_pHolder == 0) return ReturnType(); \
        return m_pHolder->call(PARAM_LIST); \
    } \
\
    bool equals(const SuperType* pDelegate) const \
    { \
        const SelfType* pRhs = dynamic_cast<const SelfType*>(pDelegate); \
        if (pRhs == 0) return false; \
\
        SelfType* temp = 0; \
        const SelfType* pClone; \
        cloneForComparison(pRhs, pClone, temp, typename ThreadingModelType::ThreadTag()); \
\
        typename ThreadingModelType::Lock guard(*this); \
        CallbackHolder* ptr1 = m_pHolder; \
        CallbackHolder* ptr2 = pClone->m_pHolder; \
        while (ptr1 != 0 && ptr2 != 0) \
        { \
            if (!ptr1->instance->equals(ptr2->instance)) \
                break; \
            ptr1 = ptr1->prev; \
            ptr2 = ptr2->prev; \
        } \
        delete temp; \
        return (ptr1 == 0 && ptr2 == 0); \
    } \
\
    SelfType* clone() const \
    { \
        SelfType* pClone = new SelfType(); \
        typename ThreadingModelType::Lock guard(*this); \
        CallbackHolder* ptr = m_pHolder; \
        CallbackHolder* pReverse = 0; \
        while (ptr != 0) \
        { \
            CallbackHolder* pHolder = new CallbackHolder(); \
            pHolder->instance = ptr->instance->clone(); \
            pHolder->prev = pReverse; \
            pReverse = pHolder; \
            ptr = ptr->prev; \
        } \
\
        CallbackHolder* prev = 0; \
        while (pReverse != 0) \
        { \
            CallbackHolder* next = pReverse->prev; \
            pReverse->prev = prev; \
            prev = pReverse; \
            pReverse = next; \
        } \
        pClone->m_pHolder = prev; \
\
        return pClone; \
    } \
\
    void add(ReturnType (*ptr)(TYPE_LIST)) \
    { \
        SuperType* pNew = new local::NativeCallback<ReturnType(TYPE_LIST)>(ptr); \
        this->addImpl(pNew); \
    } \
\
    template <typename ObjectType> \
    void add(const ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST) const) \
    { \
        SuperType* pNew = new local::MemberCallback<ObjectType, ReturnType(TYPE_LIST)>(t, ptr); \
        this->addImpl(pNew); \
    } \
\
    template <typename ObjectType> \
    void add(ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST), bool needDelete = false) \
    { \
        SuperType* pNew = new local::MemberCallback<ObjectType, ReturnType(TYPE_LIST)> \
                (t, ptr, needDelete); \
        this->addImpl(pNew); \
    } \
\
    template <typename ObjectType> \
    void add(ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST) const, \
            bool needDelete = false) \
    { \
        SuperType* pNew = new local::MemberCallback<ObjectType, ReturnType(TYPE_LIST)> \
            (t, ptr, needDelete); \
        this->addImpl(pNew); \
    } \
\
    template <typename FunctorType> \
    void add(FunctorType* pFunctor, bool needDelete = false) \
    { \
        this->add(pFunctor, &FunctorType::operator(), needDelete); \
    } \
\
    template <typename FunctorType> \
    void add(const FunctorType* pFunctor) \
    { \
        this->add(pFunctor, &FunctorType::operator()); \
    } \
\
    void add(const SelfType& rhs) \
    { \
        SelfType* pClone = rhs.clone(); \
        this->addImpl(pClone); \
    } \
\
    void remove(ReturnType (*ptr)(TYPE_LIST)) \
    { \
        SuperType* pNew = new local::NativeCallback<ReturnType(TYPE_LIST)>(ptr); \
        this->removeImpl(pNew); \
    } \
\
    template <typename ObjectType> \
    void remove(const ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST) const) \
    { \
        SuperType* pNew = new local::MemberCallback<ObjectType, ReturnType(TYPE_LIST)>(t, ptr); \
        this->removeImpl(pNew); \
    } \
\
    template <typename ObjectType> \
    void remove(ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST), bool needDelete = false) \
    { \
        SuperType* pNew = new local::MemberCallback<ObjectType, ReturnType(TYPE_LIST)> \
            (t, ptr, needDelete); \
        this->removeImpl(pNew); \
    } \
\
    template <typename ObjectType> \
    void remove(ObjectType* t, ReturnType(ObjectType::*ptr)(TYPE_LIST) const, \
            bool needDelete = false) \
    { \
        SuperType* pNew = new local::MemberCallback<ObjectType, ReturnType(TYPE_LIST)> \
            (t, ptr, needDelete); \
        this->removeImpl(pNew); \
    } \
\
    template <typename FunctorType> \
    void remove(FunctorType* pFunctor, bool needDelete = false) \
    { \
        this->remove(pFunctor, &FunctorType::operator(), needDelete); \
    } \
\
    template <typename FunctorType> \
    void remove(const FunctorType* pFunctor) \
    { \
        this->remove(pFunctor, &FunctorType::operator()); \
    } \
\
    void remove(const SelfType& rhs) \
    { \
        this->remove(rhs, typename ThreadingModelType::ThreadTag()); \
    } \
\
private: \
    void cloneForComparison(const SelfType* pRhs, const SelfType*& pClone, \
            SelfType*& ptrForDelete, SingleThreadTag) const \
    { \
        pClone = pRhs; \
        ptrForDelete = 0; \
    } \
\
    void cloneForComparison(const SelfType* pRhs, const SelfType*& pClone, \
            SelfType*& ptrForDelete, MultiThreadTag) const \
    { \
            ptrForDelete = pRhs->clone(); \
            pClone = ptrForDelete; \
    } \
\
    void copyFrom(const SelfType& rhs) \
    { \
        SelfType* pClone = rhs.clone(); \
        m_pHolder = pClone->m_pHolder; \
        pClone->m_pHolder = 0; \
        delete pClone; \
    } \
\
    void remove(const SelfType& rhs, SingleThreadTag) \
    { \
        this->removeImpl(&rhs); \
    } \
\
    void remove(const SelfType& rhs, MultiThreadTag) \
    { \
        this->removeImpl(rhs.clone()); \
    } \
\
    void addImpl(SuperType* pRhs) \
    { \
        typename ThreadingModelType::Lock guard(*this); \
        CallbackHolder* pH = new CallbackHolder(); \
        pH->instance = pRhs; \
        pH->prev = m_pHolder; \
        m_pHolder = pH; \
    } \
\
    void removeImpl(const SuperType* pRhs) \
    { \
        typename ThreadingModelType::Lock guard(*this); \
        CallbackHolder* ptr = m_pHolder; \
        CallbackHolder* prev = 0; \
        while (ptr != 0) \
        { \
            if (ptr->instance->equals(pRhs)) \
            { \
                if (prev == 0) m_pHolder = ptr->prev; \
                else prev->prev = ptr->prev; \
                delete ptr->instance; \
                delete ptr; \
                break; \
            } \
            prev = ptr; \
            ptr = ptr->prev; \
        } \
    } \
\
    void removeImpl(SuperType* pRhs) \
    { \
        const SuperType* pConst = pRhs; \
        this->removeImpl(pConst); \
        delete pRhs; \
    } \
\
private: \
    CallbackHolder* m_pHolder; \
};
#define TEMPLATE_LIST_0
#define TEMPLATE_LIST_1 TEMPLATE_LIST_0, typename T0
#define TEMPLATE_LIST_2 TEMPLATE_LIST_1, typename T1
#define TEMPLATE_LIST_3 TEMPLATE_LIST_2, typename T2
#define TEMPLATE_LIST_4 TEMPLATE_LIST_3, typename T3
#define TEMPLATE_LIST_5 TEMPLATE_LIST_4, typename T4
#define TEMPLATE_LIST_6 TEMPLATE_LIST_5, typename T5
#define TYPE_LIST_0
#define TYPE_LIST_1 T0
#define TYPE_LIST_2 TYPE_LIST_1, T1
#define TYPE_LIST_3 TYPE_LIST_2, T2
#define TYPE_LIST_4 TYPE_LIST_3, T3
#define TYPE_LIST_5 TYPE_LIST_4, T4
#define TYPE_LIST_6 TYPE_LIST_5, T5
#define TYPE_PARAM_LIST_0
#define TYPE_PARAM_LIST_1 T0 t0
#define TYPE_PARAM_LIST_2 TYPE_PARAM_LIST_1, T1 t1
#define TYPE_PARAM_LIST_3 TYPE_PARAM_LIST_2, T2 t2
#define TYPE_PARAM_LIST_4 TYPE_PARAM_LIST_3, T3 t3
#define TYPE_PARAM_LIST_5 TYPE_PARAM_LIST_4, T4 t4
#define TYPE_PARAM_LIST_6 TYPE_PARAM_LIST_5, T5 t5
#define PARAM_LIST_0
#define PARAM_LIST_1 t0
#define PARAM_LIST_2 PARAM_LIST_1, t1
#define PARAM_LIST_3 PARAM_LIST_2, t2
#define PARAM_LIST_4 PARAM_LIST_3, t3
#define PARAM_LIST_5 PARAM_LIST_4, t4
#define PARAM_LIST_6 PARAM_LIST_5, t5
DELEGATE_GENERATOR(TEMPLATE_LIST_0, TYPE_LIST_0, TYPE_PARAM_LIST_0, PARAM_LIST_0)
DELEGATE_GENERATOR(TEMPLATE_LIST_1, TYPE_LIST_1, TYPE_PARAM_LIST_1, PARAM_LIST_1)
DELEGATE_GENERATOR(TEMPLATE_LIST_2, TYPE_LIST_2, TYPE_PARAM_LIST_2, PARAM_LIST_2)
DELEGATE_GENERATOR(TEMPLATE_LIST_3, TYPE_LIST_3, TYPE_PARAM_LIST_3, PARAM_LIST_3)
DELEGATE_GENERATOR(TEMPLATE_LIST_4, TYPE_LIST_4, TYPE_PARAM_LIST_4, PARAM_LIST_4)
DELEGATE_GENERATOR(TEMPLATE_LIST_5, TYPE_LIST_5, TYPE_PARAM_LIST_5, PARAM_LIST_5)
DELEGATE_GENERATOR(TEMPLATE_LIST_6, TYPE_LIST_6, TYPE_PARAM_LIST_6, PARAM_LIST_6)
// remove the macros
#undef DELEGATE_GENERATOR
  
#undef TEMPLATE_LIST_0
#undef TEMPLATE_LIST_1
#undef TEMPLATE_LIST_2
#undef TEMPLATE_LIST_3
#undef TEMPLATE_LIST_4
#undef TEMPLATE_LIST_5
#undef TEMPLATE_LIST_6
#undef TYPE_LIST_0
#undef TYPE_LIST_1
#undef TYPE_LIST_2
#undef TYPE_LIST_3
#undef TYPE_LIST_4
#undef TYPE_LIST_5
#undef TYPE_LIST_6
#undef TYPE_PARAM_LIST_0
#undef TYPE_PARAM_LIST_1
#undef TYPE_PARAM_LIST_2
#undef TYPE_PARAM_LIST_3
#undef TYPE_PARAM_LIST_4
#undef TYPE_PARAM_LIST_5
#undef TYPE_PARAM_LIST_6
#undef PARAM_LIST_0
#undef PARAM_LIST_1
#undef PARAM_LIST_2
#undef PARAM_LIST_3
#undef PARAM_LIST_4
#undef PARAM_LIST_5
#undef PARAM_LIST_6
} // namespace
#endif // WAN_DELEGATE_H

threadingmodel.h
#ifndef WAN_THREADINGMODEL_H
#define WAN_THREADINGMODEL_H

/**
 * @author Kevin Wan <wanjunfeng@gmail.com>
 * @date   12/30/2005
 * Copyright (C) Kevin Wan
 */

namespace wan
{
struct SingleThreadTag {};
struct MultiThreadTag {};

template <typename LockType>
class ThreadingModel
{
public:
    typedef MultiThreadTag ThreadTag;

    class Lock
    {
        Lock(const Lock&);
        void operator=(const Lock&);

    public:
        explicit Lock(const ThreadingModel& host)
            : m_host(host)
        {
            m_host.m_mutex.lock();
        }
        ~Lock()
        {
            m_host.m_mutex.unlock();
        }

    private:
        const ThreadingModel& m_host;
    };

    friend class Lock;

    ThreadingModel() {}

private:
    ThreadingModel(const ThreadingModel&);
    ThreadingModel& operator=(const ThreadingModel&);

private:
    mutable LockType    m_mutex;
};

template <>
class ThreadingModel<void>
{
public:
    typedef SingleThreadTag ThreadTag;

    struct Lock
    {
        explicit Lock(const ThreadingModel&) {}
    };

    ThreadingModel() {}

private:
    ThreadingModel(const ThreadingModel&);
    ThreadingModel& operator=(const ThreadingModel&);
};
} // namespace

#endif // WAN_THREADINGMODEL_H

example.cc
#include <stdio.h>
#include "delegate.h"

const char* bar = "##########################################";

void native_func(int value)
{
    printf("%s\n", bar);
    printf("native function, value = %d\n", value);
}

class Object
{
public:
    static void static_member_func(int value)
    {
        printf("%s\n", bar);
        printf("static member function, value = %d\n", value);
    }
    void non_const_member_func(int value)
    {
        printf("%s\n", bar);
        printf("non-const member function, value = %d\n", value);
    }
    void const_member_func(int value) const
    {
        printf("%s\n", bar);
        printf("const member function, value = %d\n", value);
    }
};

class Functor
{
public:
    void operator()(int value)
    {
        printf("%s\n", bar);
        printf("non-const functor, value = %d\n", value);
    }
};

class ConstFunctor
{
public:
    void operator()(int value) const
    {
        printf("%s\n", bar);
        printf("const functor, value = %d\n", value);
    }
};

int main()
{
    typedef wan::delegate<void(int)> MyDelegate;

    Object obj;
    Functor functor;
    ConstFunctor constFunctor;
    MyDelegate dele;
    dele.add(&native_func);
    dele.add(&Object::static_member_func);
    dele.add(&obj, &Object::non_const_member_func);
    dele.add(&obj, &Object::const_member_func);
    dele.add(&functor);
    dele.add(&constFunctor);
    dele(111);

    printf("%s\n", bar);
    printf("\n\nafter remove operations\n\n");

    dele.remove(&native_func);
    dele.remove(&obj, &Object::non_const_member_func);
    dele(222);

    printf("%s\n", bar);
    printf("\n\nadd delegate object to delegate object\n\n");

    MyDelegate temp;
    temp.add(&native_func);
    temp.add(&obj, &Object::non_const_member_func);
    dele.add(&temp);
    dele(333);

    printf("%s\n", bar);
}

test.cc
#include <stdio.h>
#include "delegate.h"
// #include "mutex.h"

struct DummyLock
{
    void lock() {}
    void unlock() {}
};

void print_hello()
{
    printf("print_hello\n");
}

void print_world()
{
    printf("print_world\n");
}

class Object
{
public:
    Object() { printf("Object::Object\n"); }
    ~Object() { printf("Object::~Object\n"); }
    void print() const
    {
        printf("in Object::print\n");
    }
    void test() const
    {
        wan::delegate<void()> d;
        d.add(this, &Object::print);
        d();
    }
};

class Functor
{
public:
    void operator()() const
    {
        printf("in Functor::operator() const\n");
    }
};

int main()
{
    {
        wan::delegate<void(), DummyLock> d;
        d.add(&print_hello);
        d.add(&print_world);
        if (d.equals(&d))
            printf("the same\n");
        else
            printf("not the same\n");
        printf("\n");
        wan::delegate<void(), DummyLock>* pd = d.clone();
        if (d.equals(pd))
            printf("the same\n");
        else
            printf("not the same\n");
        delete pd;
        printf("\n");
        d();
        wan::delegate<void(), DummyLock> d1(d);
        printf("%u\n", sizeof(d));
        d.add(d);
        d();
        printf("\n");
        d.remove(d1);
        d();
    }

    /*
    {
        wan::delegate<void(), Mutex> d;
        d.add(&print_hello);
        printf("%u\n", sizeof(d));
    }
    */

    {
        wan::delegate<void()> d;
        d.add(new Object(), &Object::print, true);
        d();
        wan::delegate<void()> d1(d);
        wan::delegate<void()>* d2 = d.clone();
        d1();
        (*d2)();
        delete d2;
    }

    {
        Object obj;
        obj.test();
    }

    {
        wan::delegate<void()> d;
        d.add(new Functor(), true);
        d();
    }
}
posted on 2005-08-02 23:55  Kevin Wan  阅读(1379)  评论(0编辑  收藏