
delegate in c++ (new version)
发布日期:2021-05-09 04:09:51
浏览次数:20
分类:博客文章
本文共 19493 字,大约阅读时间需要 64 分钟。
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 adelegate object. The delegate object can then be passed to code which can call thereferenced method, without having to know at compile time which method will beinvoked.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 . 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
__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;};
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);}
发表评论
最新留言
哈哈,博客排版真的漂亮呢~
[***.90.31.176]2025年04月09日 21时50分01秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
jQuery实现日期字符串格式化
2021-05-09
vue学习笔记(十)路由
2021-05-09
[最全整理]关于决策树的一切
2021-05-09
100天搞定机器学习|Day9-12 支持向量机
2021-05-09
100天搞定机器学习|Day19-20 加州理工学院公开课:机器学习与数据挖掘
2021-05-09
100天搞定机器学习|Day22 机器为什么能学习?
2021-05-09
100天搞定机器学习|day37 无公式理解反向传播算法之精髓
2021-05-09
数据工程师必备的8项技能,不要只知道Python!
2021-05-09
R in action读书笔记(3)-第六章:基本图形
2021-05-09
R in action读书笔记(19)第十四章 主成分和因子分析
2021-05-09
iOS UIAlertController
2021-05-09
iOS UISlider的使用
2021-05-09
iOS Xcode 打包之后,不能输出日志
2021-05-09
UIPickerView的使用(二)
2021-05-09
iOS 多线程GCD简介
2021-05-09
实现延迟消息队列
2021-05-09
写了一下 micropython 的文件系统单元测试
2021-05-09
说说字库和字模的故事,然后在 MaixPy 里实现打印中文字体(任意字体)吧!
2021-05-09
线性代数应该这样学9:上三角矩阵、对角矩阵
2021-05-09