| |||
| #ifndef TCLIB_FOR_EACH_H #define TCLIB_FOR_EACH_H //**************************}H{**************************}H{************************** #ifdef _INC_COMDEF template<typename CType> struct GetTypeTrait{ typedef _COM_SMARTPTR<_COM_SMARTPTR_LEVEL2<CType, &__uuidof(CType)> > Type; typedef CType ** RefType; }; #else template<typename CType> struct GetTypeTrait{ typedef CType Type; typedef CType * RefType; }; #endif #define DEFINE_SIMPLY_GET_TRAIT(type) \ template<>struct GetTypeTrait<type>{ \ typedef type Type; \ typedef type* RefType; \ }; #define DEFINE_CUSTOM_GET_TRAIT(type,ptrType,refType) \ template<>struct GetTypeTrait<type>{ \ typedef ptrType Type; \ typedef refType RefType; \ }; DEFINE_SIMPLY_GET_TRAIT(short); DEFINE_SIMPLY_GET_TRAIT(long); DEFINE_SIMPLY_GET_TRAIT(bool); DEFINE_SIMPLY_GET_TRAIT(double); DEFINE_SIMPLY_GET_TRAIT(float); DEFINE_SIMPLY_GET_TRAIT(char); DEFINE_SIMPLY_GET_TRAIT(UINT); DEFINE_SIMPLY_GET_TRAIT(ULONG); DEFINE_SIMPLY_GET_TRAIT(GUID); #ifdef __ATLBASE_H__ DEFINE_CUSTOM_GET_TRAIT(BSTR,CComBSTR,BSTR*); DEFINE_CUSTOM_GET_TRAIT(VARIANT,CComVariant,VARIANT*); #endif //**************************}H{**************************}H{************************** //规范各种容器的子对象取值函数 //用几个宏和一个函数子来封装 #define GetI(ConType,foo,i,ItemType,obj) GetFunctor<ConType,ItemType>::GetAtFoo((ConType*)GetTypeTrait<ConType>::Type(obj),i,ConType::foo) #define GetA(ConType,foo,GetType,obj) GetFunctor<ConType,GetType>::GetFoo((ConType*)GetTypeTrait<ConType>::Type(obj),ConType::foo) #define NoGet(I,T,f,o) GetFunctor<I,T>::VoidFoo((I*)GetTypeTrait<I>::Type(o),ConType::f) template<class ObjType,typename GetType, typename OutRetType = GetTypeTrait<GetType>::Type, typename InRefType = GetTypeTrait<GetType>::RefType> struct GetFunctor{ typedef OutRetType RetType; typedef InRefType RefType; typedef HRESULT (__stdcall ObjType::* STDCALL_GET_FOO)(RefType); typedef HRESULT ( ObjType::* CCALL_GET_FOO)(RefType); typedef HRESULT (__stdcall ObjType::* STDCALL_GETAT_FOO)(long,RefType); typedef HRESULT ( ObjType::* CCALL_GETAT_FOO)(long,RefType); typedef HRESULT (__stdcall ObjType::* STDCALL_VOID_FOO)(); typedef HRESULT ( ObjType::* CCALL_VOID_FOO)(); //非COM形式的Get函数 typedef void ( ObjType::* CCALL_SIMPLY_VOID_FOO)(void); typedef void (__stdcall ObjType::* STDCALL_SIMPLY_VOID_FOO)(void); typedef OutRetType ( ObjType::* CCALL_SIMPLY_GET_FOO)(void); typedef OutRetType (__stdcall ObjType::* STDCALL_SIMPLY_GET_FOO)(void); typedef OutRetType ( ObjType::* CCALL_SIMPLY_GETAT_FOO)(long); typedef OutRetType (__stdcall ObjType::* STDCALL_SIMPLY_GETAT_FOO)(long); static bool VoidFoo(ObjType* pObj,STDCALL_VOID_FOO pFun){ if(pObj) return SUCCEEDED((pObj->*pFun)()); return false; } static bool VoidFoo(ObjType* pObj,CCALL_VOID_FOO pFun){ if(pObj) return SUCCEEDED((pObj->*pFun)()); return false; } static bool VoidFoo(ObjType* pObj,STDCALL_SIMPLY_VOID_FOO pFun){ if(!pObj) return false; (pObj->*pFun)(); return true; } static bool VoidFoo(ObjType* pObj,CCALL_SIMPLY_VOID_FOO pFun){ if(!pObj) return false; (pObj->*pFun)(); return true; } static RetType GetFoo(ObjType* pObj,STDCALL_GET_FOO pFun){ RetType ret(0); if(pObj) (pObj->*pFun)((RefType) &ret); return ret; } static RetType GetFoo(ObjType* pObj,CCALL_GET_FOO pFun){ RetType ret(0); if(pObj) (pObj->*pFun)((RefType) &ret); return ret; } static RetType GetFoo(ObjType* pObj,CCALL_SIMPLY_GET_FOO pFun){ return (pObj->*pFun)(); } static RetType GetFoo(ObjType* pObj,STDCALL_SIMPLY_GET_FOO pFun){ return (pObj->*pFun)(); } static RetType GetAtFoo(ObjType* pObj,long i,STDCALL_GETAT_FOO pFun){ RetType ret(0); if(pObj) (pObj->*pFun)(i,(RefType) &ret); return ret; } static RetType GetAtFoo(ObjType* pObj,long i,CCALL_GETAT_FOO pFun){ RetType ret(0); if(pObj) (pObj->*pFun)(i,(RefType) &ret); return ret; } static RetType GetAtFoo(ObjType* pObj,long i,STDCALL_SIMPLY_GETAT_FOO pFun){ return (pObj->*pFun)(i); } static RetType GetAtFoo(ObjType* pObj,long i,CCALL_SIMPLY_GETAT_FOO pFun){ return (pObj->*pFun)(i); } }; //**************************}H{**************************}H{************************** //容器及其子项的类型萃取器 template<typename ConType,typename ItemType> struct EnumTypesTrait{ typedef GetTypeTrait<ItemType>::Type ITEM_TYPE; typedef GetTypeTrait<ItemType>::RefType ITEM__REF_TYPE; typedef GetTypeTrait<ConType>::Type CONTAINER_TYPE; ITEM_TYPE _item; protected: EnumTypesTrait(){ _pObj = 0; } CONTAINER_TYPE _pObj; }; //预定义容器概念 //默认为是形如STL的容器 template<class ConType> struct ContainorConcept{ typedef ConType::value_type ITEM_TYPE; typedef const ConType CONTAINER_TYPE; ContainorConcept(const ConType& obj){ _pObj = (&obj); } bool Begin(){ if(_pObj->begin() == _pObj->end()) return false; _iter = const_cast<ConType::iterator>(_pObj->begin()); return true; } bool Next(){ if(_iter == _pObj->end()) return false; _item = *(_iter); ++_iter; return true; } CONTAINER_TYPE * _pObj; ITEM_TYPE _item; ConType::iterator _iter; }; //**************************}H{**************************}H{************************** //声明容器的枚举方法类型 //将一个容器声明为前向枚举器 #define DECLARE_AS_FORWARD_ENUM(ConType,ItemType,ResetFoo,NextFoo) \ template<>struct ContainorConcept<ConType> : EnumTypesTrait<ConType,ItemType>{ \ ContainorConcept(CONTAINER_TYPE pObj){ \ _pObj = pObj; \ } \ bool Begin(){ \ if(0 == _pObj) return false; \ return NoGet(ConType,ItemType,ResetFoo,_pObj); \ } \ bool Next(){ \ return 0 != (_item = GetA(ConType,NextFoo,ItemType,_pObj));\ } \ }; //将一个容器声明为单次枚举器 #define DECLARE_AS_JUSTONE_ENUM(ConType,ItemType,NextFoo) \ template<>struct ContainorConcept<ConType> : EnumTypesTrait<ConType,ItemType>{ \ ContainorConcept(CONTAINER_TYPE pObj){ \ _pObj = pObj; \ } \ bool Begin(){ \ return 0 != _pObj; \ } \ bool Next(){ \ return 0 != (_item = GetA(ConType,NextFoo,ItemType,_pObj));\ } \ }; //申明一个为随即枚举器 #define DDECLARE_AS_RANDOM_ENUM(ConType,ItemType,CountFoo,GetAtFoo) \ template<>struct ContainorConcept<ConType> : EnumTypesTrait<ConType,ItemType>{ \ ContainorConcept(CONTAINER_TYPE pObj){ \ _pObj = pObj; \ nCount = 0;i = 0; \ } \ long nCount,i; \ bool Begin(){ \ return 0 != (nCount = GetA(ConType,CountFoo,long,_pObj)); \ } \ bool Next(){ \ if(i >= nCount) return false; \ return 0 != (_item = GetI(ConType,GetAtFoo,i++,ItemType,_pObj)); \ } \ }; //**************************}H{**************************}H{************************** #define _for_each(ConType,container,item) \ {ContainorConcept< ConType > ConCpt(container); \ ContainorConcept< ConType >::ITEM_TYPE item; \ if(ConCpt.Begin()) \ while(ConCpt.Next()){ \ item = ConCpt._item; #define _end_for_each }} //**************************}H{**************************}H{************************** DECLARE_AS_JUSTONE_ENUM(ICursor,IRow,NextRow); DDECLARE_AS_RANDOM_ENUM(IArray,IUnknown,get_Count,get_Element); DDECLARE_AS_RANDOM_ENUM(ILongArray,long,get_Count,get_Element); /* #include "UnitTest.h" struct MyFWDContainer { void Reset(){ a = 100;}; long Next(){ return --a;}; long a; }; DEFINE_CUSTOM_GET_TRAIT(MyFWDContainer,MyFWDContainer*,MyFWDContainer**); DECLARE_AS_FORWARD_ENUM(MyFWDContainer,long,Reset,Next); _beg_utest(3,"MyFWDContainer UTest") MyFWDContainer a; _for_each(MyFWDContainer,&a,i) _end_for_each _end_utest _beg_utest(0,"COM Interface UTest") IArrayPtr pArr(CLSID_Array); pArr->Insert(0,(IUnknown*)pArr); pArr->Insert(1,(IUnknown*)pArr); pArr->Insert(2,(IUnknown*)pArr); _for_each(IArray,pArr,pSelf) SAY(----------------); _for_each(IArray,pSelf,pUnk) SAY2(((long)((void*)((IUnknown*)pUnk)))); _end_for_each _end_for_each _end_utest _beg_utest(1,"STD Container UTest") typedef std::vector<long> LONGARR; LONGARR LonArr; LonArr.push_back(0); LonArr.push_back(1); LonArr.push_back(2); _for_each(LONGARR,LonArr,i) SAY2(i); _end_for_each _end_utest _beg_utest(2,"STD String UTest") std::string a("Hello for each!"); _for_each(std::string,a,ch) SAY2(ch); _end_for_each _end_utest */ #endif /* */ |
| |||
| 主要是在VC里遍历COM的容器接口时感觉很罗嗦总是要 IItemPtr i; ipEnum->Reset(); ipEnum->Next(&i); while(i) { //........ ipEnum->Next(&i); }; 或者 long nCount = 0; IUnknownPtr ipUnk; ipArr->get_Count(&nCount); for(long k = 0;k < nCount; ++k) { //.... ipArr->get_Element(k,&ipUnk); //.... } 就写了这些,以后就可以这样了 _for_each(IEnumerator,ipEnum,i) //....Do(i); _end_for_each 和 _for_each(IArray,ipArr,ipUnk) //...Do(ipUnk); _end_for_each |