Skip to content

Latest commit

 

History

History
617 lines (462 loc) · 15.4 KB

File metadata and controls

617 lines (462 loc) · 15.4 KB
  1. 常用函数对象 functionobject

发布日期: 2013-10-07 13:25:50 原文链接: https://blog.csdn.net/Tonny0832/article/details/12379299


源代码可以在我的资源中去下载(包括用法测试的源代码):

http://download.csdn.net/detail/tonny0832/7426991

只需要用VS建一个空的工程,然后引入我的测试头文件即可。然后测试函数会在main函数之前运行,在控制台窗口中可以看到输出。

在使用STL算法时,第三个参数通常是一些函数对象。这样,我们为了使用STL提供的算法函数,就不得不提供一些零碎的,小的函数对象,有可能这些函数对象仅仅这只这一处使用,我们就不得不写这样一个函数对象类。大多数时候,这个函数对象提供的功能可能非常简单,比如说就是根据结构体里的某个子结构体的某个子成员值相比较,或者满足某种大小的需求,这类需求功能从概念上讲是一样的,但是实现起来,就不得不一一书写这些琐碎的函数对象。本泛型代码基于概念,实现了泛型的这些函数对象,用户可以在大部分情况下避免写自己的函数对象。

#ifndef functionObject_h__
#define functionObject_h__
/********************************************************************
Description : pack function as object, which is useful in STL algorithm .
Author : Shen.Xiaolong (Shen Tony) (2010-2013)
Mail : xlshen2002@hotmail.com, xlshen@126.com
verified platform : VS2008
copyright: : latest Version of The Code Project Open License (CPOL : http://www.codeproject.com/)
*********************************************************************/
#include "libconfig.h"
#include "macroDef.h"
#include "mathOperator.h"
#include "typeconvert.h"
#include "dataSet.h"
#include "typeTraits.h"
#include "unaryFunctionConverter.h"
#include "memberPtr.h"
#include "functionTraits.h"
#include "function.h"

namespace UtilExt
{
///Comparer implement //
//it is used to compare same type data,such as in one sequence / container / array
template<typename L,typename R,typename R_T=bool>
struct Comparer
{
typedef L TP1;
typedef R TP2;
typedef R_T Return_T;
};

template
struct NotComparor : public Comparer<typename GetBinaryFunctionParam<Comparer_T,1>::type,typename GetBinaryFunctionParam<Comparer_T,2>::type>
{
NotComparor(Comparer_T& rCmp)
: m_cmpImpl(rCmp)
{}

template<typename TL,typename TR>
Return_T operator()(TL& p1,TR& p2)
{
return !m_cmpImpl(p1,p2);
}

Comparer_T& m_cmpImpl;
};
template
NotComparor<Comparer_T> makeComparerNot(Comparer_T& rCpr)
{
return NotComparor<Comparer_T>(rCpr);
}

namespace CGetType
{
namespace Comparer
{
template
struct applyByNot : public Type2Type<NotComparor<Comparer_T> > {};
}
}

template
struct ComparerImpl : public Comparer<typename GetBinaryFunctionParam<BF_T,1>::type,typename GetBinaryFunctionParam<BF_T,2>::type>
{
explicit ComparerImpl(BF_T& f)
: m_f(f)
{
AssertXI(f.m_f,("Function pointer is NULL."));
};

template<typename TL,typename TR>
Return_T operator()(TL& p1,TR& p2)
{
return m_f(p1,p2);
}

private:
BF_T m_f;
};

template
ComparerImpl<BF_T> makeComparer(BF_T& f)
{
TRACE_COMPILE();
return ComparerImpl<BF_T>(f);
}

namespace CGetType
{
namespace Comparer
{
template
struct applyByBinaryFunction : public Type2Type<ComparerImpl<BF_T> > {};
}
}

template<typename MemPtr_T,typename BF_T>
struct ComparerByMember : public Comparer<
typename SameConst<typename GetInputParam<MemPtr_T>::type,typename GetBinaryFunctionParam<BF_T,1>::type>::type,
typename SameConst<typename GetInputParam<MemPtr_T>::type,typename GetBinaryFunctionParam<BF_T,2>::type>::type

{
explicit ComparerByMember(MemPtr_T& member,BF_T& f)
: m_member(member) , m_f(f) //f MUST be function object, instead of function pointer, else it cause C2436 compile error
{};

template<typename TL,typename TR>
Return_T operator()(TL& p1,TR& p2)
{
return m_f(m_member(p1),m_member(p2));
}

protected:
BF_T m_f;
MemPtr_T m_member;
};

template<typename MemberPtr_T,typename BF_T>
ComparerByMember<MemberPtr_T,BF_T> makeComparer(MemberPtr_T& member,BF_T& f)
{
Static_Assert((IsSameRawType<typename GetMember<MemberPtr_T>::type,typename GetBinaryFunctionParam<BF_T,1>::type>::value));
Static_Assert((IsSameRawType<typename GetMember<MemberPtr_T>::type,typename GetBinaryFunctionParam<BF_T,2>::type>::value));
return ComparerByMember<MemberPtr_T,BF_T>(member,f);
}

namespace CGetType
{
namespace Comparer
{
template<typename MemberPtr_T,typename BF_T>
struct applyByMemberCmp : public Type2Type<ComparerByMember<MemberPtr_T,BF_T> > {};
}
}

/
/
template //note : D can be const and non-const.(e.g. D can be int or const int)
struct UnaryTester
{
typedef D Param_T;
};

template<typename UF_T,typename R_T=typename GetFunctionReturnType<UF_T>::type>
struct UnaryTesterImpl : public UnaryTester< typename GetUnaryFunctionParam<UF_T>::type >
{
typedef R_T Return_T;

UnaryTesterImpl(UF_T& f,Return_T retChk)
: m_f(f)
, m_ret(retChk)
{ }

template bool operator()(TP& obj)
{
return m_ret == m_f(obj);
}

UF_T m_f;
Return_T m_ret;
};

template
UnaryTesterImpl<UF_T> makeTester(UF_T& f,TPP(typename GetFunctionReturnType<UF_T>::type) ret)
{
return UnaryTesterImpl<UF_T>(f,ret);
}

template<typename T,typename R>
UnaryTesterImpl<R (*)(T)> makeTester(R (*f)(T),TPP(R) ret)
{
typedef R (*F)(T);
return UnaryTesterImpl(f,ret);
}

namespace CGetType
{
namespace UnaryTester
{
template
struct applyByUnaryFunction : public Type2Type<UnaryTesterImpl<UF_T> > {};

template<typename T,typename R>
struct applyByUnaryFunction<R ()(T)> : public Type2Type<UnaryTesterImpl<R ()(T)> > {};
}
}

template<typename MemPtr_T,typename UF_T,typename R_T=typename GetFunctionReturnType<UF_T>::type>
struct UnaryTesterByMember
: public UnaryTester<typename SameConst<typename GetInputParam<MemPtr_T>::type,typename GetUnaryFunctionParam<UF_T>::type>::type>
{
typedef R_T Return_T;

explicit UnaryTesterByMember(MemPtr_T& member,UF_T& f,Return_T ret)
: m_member(member) , m_f(f) , m_ret(ret)
{};

template bool operator()(TP& obj)
{
return m_ret == m_f(m_member(obj));
}

protected:
Return_T m_ret;
MemPtr_T m_member;
UF_T m_f;
};

template<typename MemPtr_T,typename UF_T>
UnaryTesterByMember<MemPtr_T,UF_T> makeTester(MemPtr_T& member,UF_T& f,TPP(typename GetFunctionReturnType<UF_T>::type) retChk)
{
return UnaryTesterByMember<MemPtr_T,UF_T>(member,f,retChk);
}

template<typename T,typename R,typename MemPtr_T>
UnaryTesterByMember<MemPtr_T,UnaryFunction<R (*)(T),1> > makeTester(MemPtr_T& member,R (pF)(T),R retChk)
{
return makeTester(member,UnaryFunction<bool(
)(T),1>(pF),retChk);
}

namespace CGetType
{
namespace UnaryTester
{
template<typename MemPtr_T,typename UF_T>
struct applyByMemberCompare : public Type2Type<UnaryTesterByMember<MemPtr_T,UF_T> > {};

template<typename MemPtr_T,typename T,typename R>
struct applyByMemberCompare<MemPtr_T,R ()(T)>: public Type2Type<UnaryTesterByMember<MemPtr_T,UnaryFunction<R ()(T),1> > > {};
}
}

template<typename T1,typename T2,bool bSameRawType=IsSameRawType<T1,T2>::value,
bool bSameConst = IsConst::value==IsConst::value, bool bSameRef = IsRef::value == IsRef::value>
struct SelectCommonParam;
template<typename T1,typename T2> struct SelectCommonParam<T1,T2,true,true,true> : Type2Type {};
template<typename T1,typename T2> struct SelectCommonParam<T1,T2,true,false,false> : Type2Type {};
template<typename T1,typename T2> struct SelectCommonParam<T1,T2,true,true,false> : Type2Type<typename AddRef::type> {};
template<typename T1,typename T2> struct SelectCommonParam<T1,T2,true,false,true> : Type2Type<typename RemoveConst::type> {};

template<typename Condition_T1,typename Condition_T2>
struct UnaryTesterByMultiCondition :
public UnaryTester<typename SelectCommonParam<
typename GetUnaryFunctionParam<Condition_T1>::type,
typename GetUnaryFunctionParam<Condition_T2>::type>::type>
{
UnaryTesterByMultiCondition(Condition_T1& condi1,Condition_T2& condi2)
: m_condi1(condi1) , m_condi2(condi2) {};

template bool operator()(TP& obj)
{
return m_condi1(obj) && m_condi2(obj);
}

Condition_T1 m_condi1;
Condition_T2 m_condi2;
};

template<typename Condition_T1,typename Condition_T2>
UnaryTesterByMultiCondition<Condition_T1,Condition_T2> makeTester(Condition_T1& rCondi1,Condition_T2& rCondi2)
{
return UnaryTesterByMultiCondition<Condition_T1,Condition_T2>(rCondi1,rCondi2);
}

namespace CGetType
{
namespace UnaryTester
{
template<typename Condition_T1,typename Condition_T2>
struct applyByMultiCondition : public Type2Type<UnaryTesterByMultiCondition<Condition_T1,Condition_T2> > {};
}
}

template<typename D1,typename D2, typename MemberPtr_T>
UnaryTesterByMultiCondition<UnaryTesterByMember<MemberPtr_T,UnaryFunction<bool ()(D1,D2),1> >,
UnaryTesterByMember<MemberPtr_T,UnaryFunction<bool (
)(D1,D2),2> > >
makeRangeTester(MemberPtr_T& rMember,TPP(D1) vMin,TPP(D2) vMax,bool (pGreater)(D1,D2)/=UtilExt::greater<D1,D2>*/)
{
return makeTester(makeTester(rMember,makeUnaryFunction(pGreater,$,vMin),true),makeTester(rMember,makeUnaryFunction(pGreater,vMax,$),true));
}

template<typename D1,typename D2>
UnaryTesterByMultiCondition<UnaryTesterImpl<UnaryFunction<bool ()(D1,D2),1> >,
UnaryTesterImpl<UnaryFunction<bool (
)(D1,D2),2> > >
makeRangeTester(TPP(D1) vMin,TPP(D2) vMax,bool (pGreater)(D1,D2)/=UtilExt::greater<D1,D2>*/)
{
return makeTester(makeTester(makeUnaryFunction(pGreater,$,vMin),true),makeTester(makeUnaryFunction(pGreater,vMax,$),true));
}

namespace CGetType
{
namespace UnaryTester
{
template<typename Condition_T1,typename Condition_T2> struct applyByRange ;

template<typename D1,typename D2, typename MemberPtr_T>
struct applyByRange<MemberPtr_T,bool ()(D1,D2)> : public applyByMultiCondition<
UnaryTesterByMember<MemberPtr_T,UnaryFunction<bool (
)(D1,D2),1> >,
UnaryTesterByMember<MemberPtr_T,UnaryFunction<bool (*)(D1,D2),2> > > {};

template<typename D1,typename D2>
struct applyByRange<bool ()(D1,D2),_> : public applyByMultiCondition<
UnaryTesterImpl<UnaryFunction<bool (
)(D1,D2),1> >,
UnaryTesterImpl<UnaryFunction<bool (*)(D1,D2),2> > > {};
}
}

//
template<typename IF_T, typename DO_T>
struct IfDO
{
IfDO(IF_T& rIf,DO_T& rDo)
: m_if(rIf)
, m_do(rDo)
{ };

template bool operator()(Param_T& obj)
{
if (m_if(obj))
{
m_do(obj);
return true;
}

return false;
}

IF_T& m_if;
DO_T& m_do;
};

template<typename IF_T, typename DO_T>
IfDO<IF_T,DO_T> makeIfDO(IF_T& rIf,DO_T& rDo)
{
return IfDO<IF_T,DO_T>(rIf,rDo);
}

///Collector///
template<typename C,typename MemberPtr_T>
struct Collector
{
typedef typename CGetType::DataSet::apply::type DataSet_T;
typedef typename DataSet_T::value_type value_type;
Collector(DataSet_T& rResult,MemberPtr_T& memPtr)
: m_rResult(rResult)
, m_memPtr(memPtr)
{
}

template
void operator()(TP& obj)
{
saveResult(m_memPtr(obj));
}

DataSet_T& getResult()
{
return m_rResult;
}

protected:
template <typename DataSet_T,typename Obj_T,
bool bPtr1=IsPointer::value,
bool bPtr2=IsPointer<Obj_T>::value>
struct Saver
{
void apply(DataSet_T& rArr,Obj_T& p)
{
rArr.push_back(p);
}
};

template <typename DataSet_T,typename Obj_T>
struct Saver<DataSet_T,Obj_T,true,false>
{
void apply(DataSet_T& rArr,Obj_T& p)
{
rArr.push_back(&p);
}
};

template <typename DataSet_T,typename Obj_T>
struct Saver<DataSet_T,Obj_T,false,true>
{
void apply(DataSet_T& rArr,Obj_T& p)
{
rArr.push_back(*p);
}
};

template
void saveResult(TP& obj)
{
Saver<DataSet_T,TP> hlp;
hlp.apply(m_rResult,obj);
}

MemberPtr_T m_memPtr;
DataSet_T m_rResult;
};

template<typename C,typename MemberPtr_T>
Collector<C,MemberPtr_T> makeCollector(C& rArr,MemberPtr_T& rMemPtr)
{
return Collector<C,MemberPtr_T>(makeResult(rArr),rMemPtr);
}

//
/Apply object/
FinderImpl implement /
template
struct Finder
{
typedef typename GetUnaryFunctionParam<Tester_T>::type Param_T;
typedef typename AddPointer<typename RemoveRef<Param_T>::type>::type Result_T;

Finder(Tester_T& rTester)
: m_curObj(NULL)
, m_tester(rTester)
{};

template
bool operator()(TP& obj)
{
if (m_tester(obj))
{
m_curObj = const_cast<Result_T>(&obj);
return true;
}
return false;
}

Result_T getLastMatchedData()
{
return m_curObj;
}

mutable Result_T m_curObj;
Tester_T m_tester;
};

template
Finder<Tester_T> makeFinder(Tester_T& rTester)
{
return Finder<Tester_T>(rTester);
}

namespace CGetType
{
namespace Finder
{
template struct applyTester : public Type2Type<UtilExt::Finder<Tester_T> > {};
}
}

MaxFinder/Min FinderOld/No.x finder implement /
template
struct MaxMinFinder : public UnaryFunctionBase<typename GetBinaryFunctionParam<Comparer_T,1>::type,void>
{
typedef typename AddPointer<typename RemoveRef<Param_T>::type>::type Result_T;
public:
MaxMinFinder(Comparer_T& pCmp)
: m_comparor(pCmp)
, m_maxMinElement(NULL)
{
}

~MaxMinFinder()
{
}

void operator()(Param_T obj)
{
if (NULL == m_maxMinElement)
{
m_maxMinElement = &obj;
}
else
{
if (m_comparor(obj,*m_maxMinElement))
{
m_maxMinElement = &obj;
}
}
}

Result_T getResult()
{
return m_maxMinElement;
}

protected:
Comparer_T& m_comparor;
mutable Result_T m_maxMinElement;
};

template
MaxMinFinder<Comparer_T> makeMaxMinFinder(Comparer_T& rComparer)
{
return MaxMinFinder<Comparer_T>(rComparer);
}

}
//
VS2008 issue : it might be C++ issue, it needs perfect forward support. C++0x has resolved this issue.
VS2008 compiler doesn't support C++0x : it can't recognize the const qualifier after first function parameter.
e.g. R (
)(T1, const T2) ==> it recognize it as : R ()(T1, T2)
e.g. R (
)(T1, const T2, const T3) ==> it recognize it as : R ()(T1, T2,T3)
it only work well for the qualifier on first function parameter : R (
)(const T1,T2,T3)
pls verify this bug : obverse the variable "f" in VS2008 debug window
test code begin //
struct tagS{};
bool VSBug(tagS const& l, const tagS r){ return true;};
template void showType(T f) { };
void main()
{
showType(VSBug);
};
test code end //

debug window output:
f 0x010a2020 VSBug(const tagS &, const tagS) bool (const tagS &, tagS)*
Type is bool (const tagS &, tagS)* ==> it is wrong
data type is VSBug(const tagS &, const tagS) ==> it is correct
//*/
#endif // functionObject_h__