模板重载or编译器的小技巧

    技术2022-05-11  83

    最近在思考怎样在C++中方便的实现委托,看了很多文章,但由于C++中对类非静态成员函数指针的调用比较特殊,一直以来没有找到很好的方法实现,直到最近在CodeProject上看到一篇关于C++中委托实现的方法,惊叹于作者高深的程序艺术,竟然可以重载模板类,通过同一个类来实例化多个不同参数个数,不同参数类型的函数指针,实现封装调用函数,最终实现委托,原文连接为http://www.codeproject.com/cpp/FastDelegate.asp 俺试着学习了其中一些方法(只能看懂一部分 - -!),成果如下 类成员函数调用的实现:     // 首先声明该需要重载的模板类     //  注意:此处的类型Signature非常特殊,在后面的定义中编译器即把重载的所有类型声明参数看做是一个参数     //       编译器会将<C, R ( T1, T2 ... TN ) >中的所有参数匹配到声明中来     //       其中:C对应于声明中的C, 而R ( T1, T2 ... TN )看作是一个类型参数Signature     //  只有这样才能编译通过,否则重载不成功,编译器会报too many template arguments错误            // C为类类型, Signature为类成员函数指针类型( R (T1, T2 ... Tn) )     template<class C, typename Signature>     class MFunctor;        // N=0 没有参数     template<class C, typename R>     class MFunctor<C, R ()>     {     public:         MFunctor(C *pObj, R (C::* pFunc)())             :m_pObj(pObj), m_pFunc(pFunc)         {                    }            public:         R Invoke()         {             return (m_pObj->*m_pFunc)();         }     private:         C * m_pObj;         R (C::* m_pFunc)();     };    // class TFunctor0     // N=1 有一个参数     template<class C, typename R, typename T>     class MFunctor<C, R (T)>     {     public:         MFunctor(C *pObj, R (C::* pFunc)(T))             :m_pObj(pObj), m_pFunc(pFunc)         {                    }        public:         R Invoke(T t)         {             return (m_pObj->*m_pFunc)(t);         }     private:         C * m_pObj;         R (C::* m_pFunc)(T);     };    // class TFunctor1     // N=2 有二个参数     template<class C, typename R, typename T1, typename T2>     class MFunctor<C, R (T1, T2)>     {     public:         MFunctor(C *pObj, R (C::* pFunc)(T1, T2))             :m_pObj(pObj), m_pFunc(pFunc)         {                    }            public:         R Invoke(T1 t1, T2 t2)         {             return (m_pObj->*m_pFunc)(t1, t2);         }     private:         C * m_pObj;         R (C::* m_pFunc)(T1, T2);     };    // class TFunctor2 封装类成员函数以及普通函数的实现     //     // 封装调用普通函数指针、类静态函数指针以及类非静态函数指针的实现     // 其中只有类非静态成员函数指针的调用比较特别,需要提供类实体才能实现调用,     // 所以通过模板类MFunctor来封装调用各种类成员函数        //     // <typename Signature>中的Signature表示需要重载的特殊参数,     // 比如<R ()>, <R (T1, T2 ... Tn)>, <C (R ())>, <C (R (T1, T2 ... Tn))>     // 这个特殊参数比较特别,需要以这种形式才能编译通过 type ( ... )     template<typename Signature>     class Functor;     // N=0    //     template<class C, typename R>     class Functor<C (R ())>     {     public:         Functor(MFunctor<C, R ()> tfunctor)             :m_TFunctor(tfunctor)         {         }                 Functor(C *pObj, R (C::* pFunc)())             :m_TFunctor(pObj, pFunc)         {         }     public:         R Invoke()         {             return m_TFunctor.Invoke();         }     private:         MFunctor<C, R ()> m_TFunctor;     };     template<typename R>     class Functor<R ()>     {     public:         Functor(R (*pFunc)())             :m_pFunc(pFunc)         {         }     public:         R Invoke()         {             return m_pFunc();         }     private:         R (*m_pFunc)();     };    // Functor0     // N=1    //     template<class C, typename R, typename T>     class Functor<C (R (T))>     {     public:         Functor(MFunctor<C, R (T)> tfunctor)             :m_TFunctor(tfunctor)         {         }         Functor(C *pObj, R (C::* pFunc)(T))             :m_TFunctor(pObj, pFunc)         {         }     public:         R Invoke(T t)         {             return m_TFunctor.Invoke(t);         }     private:         MFunctor<C, R (T)> m_TFunctor;     };     template<typename R, typename T>     class Functor<R (T)>     {     public:         Functor(R (*pFunc)(T))             :m_pFunc(pFunc)         {         }     public:         R Invoke(T t)         {             return m_pFunc(t);         }     private:         R (*m_pFunc)(T);     };    // Functor1     // N=2    //     template<class C, typename R, typename T1, typename T2>     class Functor<C (R (T1, T2))>     {     public:         Functor(MFunctor<C, R (T1, T2)> tfunctor)             :m_TFunctor(tfunctor)         {         }         Functor(C *pObj, R (C::* pFunc)(T1, T2))             :m_TFunctor(pObj, pFunc)         {         }     public:         R Invoke(T1 t1, T2 t2)         {             return m_TFunctor.Invoke(t1, t2);         }     private:         MFunctor<C, R (T1, T2)> m_TFunctor;     };     template<typename R, typename T1, typename T2>     class Functor<R (T1, T2)>     {     public:         Functor(R (*pFunc)(T1, T2))             :m_pFunc(pFunc)         {         }     public:         R Invoke(T1 t1, T2 t2)         {             return m_pFunc(t1, t2);         }     private:         R (*m_pFunc)(T1, T2);     };    // Functor2 这样一类想要调用某个函数就非常容易了,例如     Functor<void ()> functor0(&TestPrint);     functor0.Invoke();        Functor<TestClass(void ())> cFunctor0(&ctest, &TestClass::TestPrint);     cFunctor0.Invoke(); 虽然这样实现代码非常漂亮,但是却有个很大的缺陷,因为R (T1, T2 ... Tn)这样的参数定义非常新颖,只有最新的编译器才支持(vs2005编译通过!),所以留下一个疑惑!这究竟是真正的函数重载实现呢,还是特殊编译器的一个动态编译技巧?本人在网上还没找到相关的具体说明,希望了解的牛人路过指点下,如果能给出详细说明的连接,俺就先拜谢了!

    最新回复(0)