9) 常用函数对象functionobject [原创,泛型编程,自由下载转载,需注明出处]

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

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<typename Comparer_T>
    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<typename Comparer_T>
    NotComparor<Comparer_T> makeComparerNot(Comparer_T& rCpr)
    {
        return NotComparor<Comparer_T>(rCpr);
    }


    namespace CGetType
    {
        namespace Comparer
        {
            template<typename Comparer_T>
            struct applyByNot : public Type2Type<NotComparor<Comparer_T> > {};
        }
    }
    
    template<typename BF_T>
    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<typename BF_T>
ComparerImpl<BF_T> makeComparer(BF_T& f)
{
        TRACE_COMPILE();
return ComparerImpl<BF_T>(f);
}


    namespace CGetType
    {
        namespace Comparer
        {
            template<typename BF_T>
            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<typename D> //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<typename TP> bool operator()(TP& obj)
        {
            return m_ret == m_f(obj);
        }


        UF_T                m_f;
        Return_T            m_ret;
    };


    template<typename UF_T>
    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>(f,ret);
    }  


    namespace CGetType
    {
        namespace UnaryTester
        {
            template<typename UF_T>
            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<typename TP> 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<T1>::value==IsConst<T2>::value, bool bSameRef = IsRef<T1>::value == IsRef<T2>::value>
struct SelectCommonParam; 
template<typename T1,typename T2> struct SelectCommonParam<T1,T2,true,true,true>    : Type2Type<T1> {};
template<typename T1,typename T2> struct SelectCommonParam<T1,T2,true,false,false>  : Type2Type<T1> {};
template<typename T1,typename T2> struct SelectCommonParam<T1,T2,true,true,false>   : Type2Type<typename AddRef<T1>::type>      {};
template<typename T1,typename T2> struct SelectCommonParam<T1,T2,true,false,true>   : Type2Type<typename RemoveConst<T1>::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<typename TP> 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<typename Param_T> 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<C>::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<typename TP>
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<typename DataSet_T::value_type>::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<typename TP>
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<typename Tester_T>
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<typename TP>
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<typename Tester_T>
Finder<Tester_T> makeFinder(Tester_T& rTester)
{
return Finder<Tester_T>(rTester);
}


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


    MaxFinder/Min FinderOld/No.x finder implement /
    template<typename Comparer_T>
    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<typename Comparer_T>
    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<typename T> 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__

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值