Utility module of Software Architecture Design -- Functor

Source: Internet
Author: User

I. Preface to implement a generalized imitation function, a generalized imitation function encapsulates "requests (functions)" and stores them in objects with "value Semantics, therefore, it supports copying, assigning values, and passing values as function parameters (pass by value ). This object can indirectly process the encapsulated requests, similar to the function in boost. This implementation adopts the solution in Modern C ++ Design. In more detail, it has the following features: 1. It can encapsulate any processing request. It can accept function pointers, member function pointers, imitation functions, and even other generalized imitation functions. 2. It is type-safe and does not match the wrong type to the wrong function. 3. It is an object with "value Semantics ". First, we will introduce the callable body in C ++: 1. c-style functions: void fun (); 2. c-style function pointer (C like pointto function): void (* pFun) (); 3. the behavior of a function reference is essentially similar to that of a const pointer to function. 4. The functor class customizes the operator () object. 5. operator. * And operator-> * execution result 6. you can add a pair of parentheses () to the right of a constructor and add a set of appropriate parameters to it. To encapsulate a function request into an object, how can we determine the function parameters? Here typelist is used (this is a type set, in other words, it contains the type list ). Here, typelist can be used as a template parameter of HTFunctor, which contains the parameter type information of the function to be encapsulated. Next we will first introduce the implementation of typelist 2: HTTypeList [cpp] <span style = "font-weight: normal;"> <span style = "font-size: 14px; "> template <class T, class U> struct HTTypeList {typedef T Head; typedef U Tail ;}; </span> This is the basic implementation of typelist (only two types are required). Now the question is how to connect n types into a linked list. Take the following example to understand [cpp] typedef HTTypeList <char, HTTypeList <int, int> (derived using template parameters and automatically generated by the compiler rather than during runtime ), in this way, both of the above parameters are solved. Now the question is how to define a parameter's typelist. The method is that the second template parameter is set to NullType (null type), so that each typelist ends with NullType, which is equivalent to the \ 0 Function of the C string. See the NullType implementation: [cpp] class HTNullType {}; then we will produce typelist (one parameter, two parameters, three parameters ......). Macros are used here. Currently, four typelist types are defined. [Cpp] # define TYPELIST_1 (T1) UTIL: HTTypeList <T1, UTIL: HTNullType> # define TYPELIST_2 (T1, T2) UTIL: HTTypeList <T1, TYPELIST_1 (T2)> # define TYPELIST_3 (T1, T2, T3) UTIL: HTTypeList <T1, TYPELIST_2 (T2, T3)> # define TYPELIST_4 (T1, T2, T3, t4) UTIL: HTTypeList <T1, TYPELIST_3 (T2, T3, T4)> another problem to be solved is that the function parameter is of the value type (internal type) or reference type (for objects ). Selecting a proper type can obviously increase the program speed. You certainly don't want to pass large object parameters and sometimes need to copy them. Next, this is coming soon -- (HTTypeTraits) 3: HTTypeTraits is a generic technology that can be used to "judge by type during compilation. You can also refer to the type traits in boost. [Cpp] // determine whether T and U indicate the same template type <typename T, typename U> struct HTIsSameType {private: template <typename> struct In {enum {value = false };}; template <> struct In <T> {enum {value = true };}; public: enum {value = In <U >:: value };}; [cpp] // select one of the two types according to flag, true is T, false is U template <bool flag, typename T, typename U> struct HTSelect {private: template <bool> struct In {typedef T Result ;}; Template <> struct In <false> {typedef U Result;}; public: typedef typename In <flag >:: Result ;}; [cpp] // type typedef char HTYes of the bool type during compilation; struct HTNo {char padding [8] ;}; // type ing is a type, which is used to differentiate template functions, the C ++ standard template function cannot be biased towards a special template <typename T> struct HTType2Type {typedef T Type ;}; // determine whether T is a class template <typename T> struct HTIsClass {// U is a class, this overload function is implemented because the parameter is a function pointer, that is, the function pointer template <typename U> static HTYe pointing to the member S IsClassTest (void (U: *) (void); // if U is not a class, this overload function // C ++ standard will be implemented: template <typename U> static HTNo IsClassTest (...); // For sizeof, the expression is not actually evaluated. The Compiler only exports the type of the result returned by the expression, therefore, you only need to declare the function to static const bool value = sizeof (IsClassTest <T> (0) = sizeof (HTYes );}; // determine whether T is of the reference type template <typename T> struct HTIsReference {template <typename U> static HTYes IsReference (HTType2Type <U &> ); Template <typename U> static HTNo IsReference (...); static const bool value = sizeof (IsReference (HTType2Type <T> () = sizeof (HTYes) ;}; template <typename T> class HTTypeTraits {public: enum {isVoid = HTIsSameType <T, void >:: value | HTIsSameType <T, const void >:: value | HTIsSameType <T, volatile void> :: value | HTIsSameType <T, const volatile void >:: value}; enum {isReference = HTIsReference <T> :: Value}; private: template <bool IsRef> struct AdjReference {template <typename U> struct In {typedef U const & Result ;};}; template <> struct AdjReference <true> {template <typename U> struct In {typedef U Result ;}}; typedef typename AdjReference <isReference | isVoid> :: template In <T>: Result AdjType; // select the type of the function parameter correctly. // For the precise type (with extra calls of constructor and destructor), use the reference parameter, for pure numeric type (numeric type, enumeration type, pointer, pointer to member), directly pass the value typedef t Ypename HTSelect <HTIsClass <T >:: value, AdjType, T >:: Result ParmType ;}; 4: HTFunctorHTTypeList and HTTypeTraits provide our powerful functions. This makes it easier for us to implement HTFunctor. See the code below. [Cpp] // The Functor object is obviously a small object. Here we use the small object distributor // use the Command mode and IMPL mode template <typename R> struct HTFunctorImplBase: public HTSmallObject <> {typedef R ResultType; typedef HTEmptyType Parm1; typedef HTEmptyType Parm2 ;}; template <typename R, class TList, class ObjClass> struct HTFunctorImpl; // No parameter version template <typename R, class ObjClass> struct HTFunctorImpl <R, HTNullType, ObjClass>: public HTFunctorImpl Base <R> {typedef R ResultType; virtual ResultType operator () (ObjClass * pObj) = 0; virtual HTFunctorImpl * Clone () const = 0; virtual ~ HTFunctorImpl () {}}; // a parameter version template <typename R, typename P1, class ObjClass> struct HTFunctorImpl <R, TYPELIST_1 (P1), ObjClass>: public HTFunctorImplBase <R> {typedef R ResultType; typedef typename HTTypeTraits <P1 >:: ParmType Parm1; virtual ResultType operator () (Parm1, ObjClass * pObj) = 0; virtual HTFunctorImpl * Clone () const = 0; virtual ~ HTFunctorImpl () {}}; // two parameter versions: template <typename R, typename P1, typename P2, class ObjClass> struct HTFunctorImpl <R, TYPELIST_2 (P1, P2 ), objClass>: public partition <R> {typedef R ResultType; typedef typename HTTypeTraits <P1 >:: ParmType Parm1; typedef typename HTTypeTraits <P2 >:: ParmType Parm2; virtual ResultType operator () (Parm1, Parm2, ObjClass * pObj) = 0; virtual HTFunctorImpl * Clone () Const = 0; virtual ~ HTFunctorImpl () {}}; // The callable body (that is, the encapsulated processing function) is the imitation function template <class ParentFunctor, typename Fun, class ObjClass> class HTFunctorHandler: public sector <typename ParentFunctor: ResultType, typename ParentFunctor: ParmList, ObjClass> {typedef typename category: Impl Base; public: typedef typename Base: ResultType; typedef typename Base:: Parm1 Parm1; typedef typename Base: Parm1 Parm2; HTFunctorHandler (const Fun & fun): m_fun (fun) {} HTFunctorHandler * Clone () const {return new HTFunctorHandler (* this);} ResultType operator () (ObjClass * pObj) {return m_fun ();} ResultType operator () (Parm1 p1, ObjClass * pObj) {return m_fun (p1);} ResultType operator () (Parm1 p1, Parm2 p2, ObjClass * pObj) {return m_fun (p1, p2);} private: Fun m_fun ;}; // The callable body (that is, the encapsulated processing function) is a class member function. To call this function, you must pass the Object Pointer template <class ParentFunctor, typename Fun, class ObjClass> class HTMemFunHandler: public sector <typename ParentFunctor: ResultType, typename ParentFunctor: ParmList, ObjClass> {typedef typename category: Impl Base; public: typedef typename Base: ResultType; typedef typename Base:: Parm1 Parm1; typedef typename Base: Parm1 Parm2; HTMemFunHandler (const Fun & fun): m_fun (fun) {} HTMemFunHandler * Clone () const {return new HTMemFunHandler (* this);} ResultType operator () (ObjClass * pObj) {return (pObj-> * m_fun) ();} ResultType operator () (Parm1 p1, ObjClass * pObj) {return (pObj-> * m_fun) (p1);} ResultType operator () (Parm1 p1, Parm2 p2, ObjClass * pObj) {return (pObj-> * m_fun) (p1, p2);} private: Fun m_fun;}; // HTFunctor template <typename R, class TList = YKNullType, class ObjClass = YKEmptyType> class HTFunctor {typedef HTFunctorImpl <R, TList, ObjClass> Impl; public: typedef R ResultType; typedef TList ParmList; typedef typename Impl: Parm1 Parm1; typedef typename Impl: Parm2 Parm2; HTFunctor (): m_spImpl () {} HTFunctor (const HTFunctor & rhs): m_spImpl (rhs. m_spImpl-> Clone () {} explicit HTFunctor (std: auto_ptr <Impl> spImpl): m_spImpl (spImpl) {} HTFunctor & operator = (const HTFunctor & rhs) {HTFunctor copy (rhs); Impl * p = m_spImpl.release (); m_spImpl.reset (copy. m_spImpl.release (); copy. m_spImpl.reset (p); return * this;} template <typename Fun> HTFunctor (Fun fun): m_spImpl (new HTSelect <HTIsSameType <ObjClass, HTEmptyType>: value, HTFunctorHandler <HTFunctor, fun, ObjClass>, HTMemFunHandler <HTFunctor, Fun, ObjClass >:: Result (fun) {} ResultType operator () (ObjClass * pObj = HT_NULL) {return (* m_spImpl) (pObj);} ResultType operator () (Parm1 p1, ObjClass * pObj = HT_NULL) {return (* m_spImpl) (p1, pObj);} ResultType operator () (Parm1 p1, parm2 p2, ObjClass * pObj = HT_NULL) {return (* m_spImpl) (p1, p2, pObj);} private: std: auto_ptr <Impl> m_spImpl ;};

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.