delegate in c++ (new version)
Delegate in C# is similar to a function pointer in C or C++, but it's type-safe and easy to use. Using a delegate allows the programmer to encapsulate a reference to a method inside a
delegate object. The delegate object can then be passed to code which can call the
referenced method, without having to know at compile time which method will be
invoked.
This C++ delegate library implements the similar concept. You can use it to as type-safe callback, thread entry routine etc.
delegate.h
__delegate.h
threadingmodel.h
example.cc
This C++ delegate library implements the similar concept. You can use it to as type-safe callback, thread entry routine etc.
you can download it from here.
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 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
#define TEMPLATE_LIST TEMPLATE_LIST_0
#define TYPE_LIST TYPE_LIST_0
#define TYPE_PARAM_LIST TYPE_PARAM_LIST_0
#define PARAM_LIST PARAM_LIST_0
#include "__delegate.h"
#undef TEMPLATE_LIST
#undef TYPE_LIST
#undef TYPE_PARAM_LIST
#undef PARAM_LIST
#define TEMPLATE_LIST TEMPLATE_LIST_1
#define TYPE_LIST TYPE_LIST_1
#define TYPE_PARAM_LIST TYPE_PARAM_LIST_1
#define PARAM_LIST PARAM_LIST_1
#include "__delegate.h"
#undef TEMPLATE_LIST
#undef TYPE_LIST
#undef TYPE_PARAM_LIST
#undef PARAM_LIST
#define TEMPLATE_LIST TEMPLATE_LIST_2
#define TYPE_LIST TYPE_LIST_2
#define TYPE_PARAM_LIST TYPE_PARAM_LIST_2
#define PARAM_LIST PARAM_LIST_2
#include "__delegate.h"
#undef TEMPLATE_LIST
#undef TYPE_LIST
#undef TYPE_PARAM_LIST
#undef PARAM_LIST
#define TEMPLATE_LIST TEMPLATE_LIST_3
#define TYPE_LIST TYPE_LIST_3
#define TYPE_PARAM_LIST TYPE_PARAM_LIST_3
#define PARAM_LIST PARAM_LIST_3
#include "__delegate.h"
#undef TEMPLATE_LIST
#undef TYPE_LIST
#undef TYPE_PARAM_LIST
#undef PARAM_LIST
#define TEMPLATE_LIST TEMPLATE_LIST_4
#define TYPE_LIST TYPE_LIST_4
#define TYPE_PARAM_LIST TYPE_PARAM_LIST_4
#define PARAM_LIST PARAM_LIST_4
#include "__delegate.h"
#undef TEMPLATE_LIST
#undef TYPE_LIST
#undef TYPE_PARAM_LIST
#undef PARAM_LIST
#define TEMPLATE_LIST TEMPLATE_LIST_5
#define TYPE_LIST TYPE_LIST_5
#define TYPE_PARAM_LIST TYPE_PARAM_LIST_5
#define PARAM_LIST PARAM_LIST_5
#include "__delegate.h"
#undef TEMPLATE_LIST
#undef TYPE_LIST
#undef TYPE_PARAM_LIST
#undef PARAM_LIST
#define TEMPLATE_LIST TEMPLATE_LIST_6
#define TYPE_LIST TYPE_LIST_6
#define TYPE_PARAM_LIST TYPE_PARAM_LIST_6
#define PARAM_LIST PARAM_LIST_6
#include "__delegate.h"
#undef TEMPLATE_LIST
#undef TYPE_LIST
#undef TYPE_PARAM_LIST
#undef PARAM_LIST
// remove the macros
#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
#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 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
#define TEMPLATE_LIST TEMPLATE_LIST_0
#define TYPE_LIST TYPE_LIST_0
#define TYPE_PARAM_LIST TYPE_PARAM_LIST_0
#define PARAM_LIST PARAM_LIST_0
#include "__delegate.h"
#undef TEMPLATE_LIST
#undef TYPE_LIST
#undef TYPE_PARAM_LIST
#undef PARAM_LIST
#define TEMPLATE_LIST TEMPLATE_LIST_1
#define TYPE_LIST TYPE_LIST_1
#define TYPE_PARAM_LIST TYPE_PARAM_LIST_1
#define PARAM_LIST PARAM_LIST_1
#include "__delegate.h"
#undef TEMPLATE_LIST
#undef TYPE_LIST
#undef TYPE_PARAM_LIST
#undef PARAM_LIST
#define TEMPLATE_LIST TEMPLATE_LIST_2
#define TYPE_LIST TYPE_LIST_2
#define TYPE_PARAM_LIST TYPE_PARAM_LIST_2
#define PARAM_LIST PARAM_LIST_2
#include "__delegate.h"
#undef TEMPLATE_LIST
#undef TYPE_LIST
#undef TYPE_PARAM_LIST
#undef PARAM_LIST
#define TEMPLATE_LIST TEMPLATE_LIST_3
#define TYPE_LIST TYPE_LIST_3
#define TYPE_PARAM_LIST TYPE_PARAM_LIST_3
#define PARAM_LIST PARAM_LIST_3
#include "__delegate.h"
#undef TEMPLATE_LIST
#undef TYPE_LIST
#undef TYPE_PARAM_LIST
#undef PARAM_LIST
#define TEMPLATE_LIST TEMPLATE_LIST_4
#define TYPE_LIST TYPE_LIST_4
#define TYPE_PARAM_LIST TYPE_PARAM_LIST_4
#define PARAM_LIST PARAM_LIST_4
#include "__delegate.h"
#undef TEMPLATE_LIST
#undef TYPE_LIST
#undef TYPE_PARAM_LIST
#undef PARAM_LIST
#define TEMPLATE_LIST TEMPLATE_LIST_5
#define TYPE_LIST TYPE_LIST_5
#define TYPE_PARAM_LIST TYPE_PARAM_LIST_5
#define PARAM_LIST PARAM_LIST_5
#include "__delegate.h"
#undef TEMPLATE_LIST
#undef TYPE_LIST
#undef TYPE_PARAM_LIST
#undef PARAM_LIST
#define TEMPLATE_LIST TEMPLATE_LIST_6
#define TYPE_LIST TYPE_LIST_6
#define TYPE_PARAM_LIST TYPE_PARAM_LIST_6
#define PARAM_LIST PARAM_LIST_6
#include "__delegate.h"
#undef TEMPLATE_LIST
#undef TYPE_LIST
#undef TYPE_PARAM_LIST
#undef PARAM_LIST
// remove the macros
#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
__delegate.h
/**
* @author Kevin Wan <wanjunfeng@gmail.com>
* @date 06/30/2005
* Copyright (C) Kevin Wan
*/
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;
};
* @author Kevin Wan <wanjunfeng@gmail.com>
* @date 06/30/2005
* Copyright (C) Kevin Wan
*/
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;
};
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
#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);
}
#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);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)