C++模板问题与其他参数

问题描述:

我有一个情况(在嵌入式系统上),我想从另一个任务调用函数。我发现这种方法是这样做的http://www.drdobbs.com/elegant-function-call-wrappers/184401385。但我该怎么做更多的争论。最好的情况我有一个解决方案,这是在模板中,但我不知道如何实现这一点。无论如何,也可以创建如下所示的两个太阳穴(在一个小型的Visual Studio C++测试中)。除了给出编译时错误的DeferCall2调用之外,一切正常。我在这里犯了什么错误?C++模板问题与其他参数

#include "stdafx.h" 
#include "stdlib.h" 
#include "stdio.h" 



class Functor 
{ 
public: 
    virtual ~Functor() {} 
    virtual void operator()() = 0; 
}; 
template< class CalleePtr, class MemFunPtr, class Parm1 > 
class MemberFunctor1 : public Functor 
{ 
public: 
    MemberFunctor1 
     (
     const CalleePtr & pCallee, 
     const MemFunPtr & pFunction, 
     Parm1 aParm1 
     ) : 
     pCallee(pCallee), 
     pFunction(pFunction), 
     aParm1(aParm1) 
    { 
    } 

    virtual void operator()() 
    { 
     if ((pCallee != NULL) && 
      (pFunction != NULL)) 
     { 
      ((*pCallee).*pFunction)(aParm1); 
     } 
    } 

private: 
    CalleePtr pCallee; 
    MemFunPtr pFunction; 
    Parm1 aParm1; 
}; 

template< class CalleePtr, class MemFunPtr, class Parm1, class Parm2 > 
class MemberFunctor2 : public Functor 
{ 
public: 
    MemberFunctor2 
     (
     const CalleePtr & pCallee, 
     const MemFunPtr & pFunction, 
     Parm1 aParm1, 
     Parm2 aParm2 
     ) : 
     pCallee(pCallee), 
     pFunction(pFunction), 
     aParm1(aParm1), 
     aParm2(aParm2) 
    { 
    } 

    virtual void operator()() 
    { 
     if ((pCallee != NULL) && 
      (pFunction != NULL)) 
     { 
      ((*pCallee).*pFunction)(aParm1, aParm2); 
     } 
    } 

private: 
    CalleePtr pCallee; 
    MemFunPtr pFunction; 
    Parm1 aParm1; 
    Parm2 aParm2; 
}; 

template< class CalleePtr, class Callee, class Ret, class Type1, class Parm1 > 
inline Functor * DeferCall 
(
const CalleePtr & pCallee, 
Ret(Callee::*pFunction)(Type1), 
const Parm1 & rParm1 
) 
{ 
    return new 
     MemberFunctor1< CalleePtr, 
     Ret(Callee::*)(Type1), Parm1 > 
     (pCallee, pFunction, rParm1); 
} 

template< class CalleePtr, class Callee, class Ret, class Type1, class Parm1, class Parm2> 
Functor * DeferCall2 
(
    const CalleePtr & pCallee, 
    Ret(Callee::*pFunction)(Type1), 
    const Parm1 & rParm1, 
    const Parm2 & rParm2 
) 
{ 
    return new 
     MemberFunctor2< CalleePtr, 
     Ret(Callee::*)(Type1), Parm1, Parm2 > 
     (pCallee, pFunction, rParm1, rParm2); 
} 

class TestObj 
{ 
public: 
    void test1 (int a) 
    { 
     printf("test 1 a=%d\r\n", a); 
    } 

    void test2 (int a, int b) 
    { 
     printf("test 2 a=%d, b=%d\r\n", a, b); 
    } 

    void test (void) 
    { 
     Functor * pCall = DeferCall(this, &TestObj::test1, 3); 

     Functor * pCall1 = new MemberFunctor1 < TestObj *, void (TestObj::*)(int), int >(this, &TestObj::test1, 6); 

     Functor * pCall2 = new MemberFunctor2 < TestObj *, void (TestObj::*)(int, int), int, int >(this, &TestObj::test2, 4, 5); 

     Functor * pCall3 = DeferCall2(this, &TestObj::test2, 3, 3); // Compile time error. 

     if (pCall) 
      (*pCall)(); 
     if (pCall1) 
      (*pCall1)(); 
     if (pCall2) 
      (*pCall2)(); 
     if (pCall3) 
      (*pCall3)(); 

     delete pCall; 
     delete pCall1; 
     delete pCall2; 
     delete pCall3; 
    } 
}; 


int _tmain(int argc, _TCHAR* argv[]) 
{ 
    TestObj *obj = new TestObj(); 
    obj->test(); 
    delete obj; 

    return 0; 
} 

你忘了在函数的第二个int型参数:

template <class CalleePtr, class Callee, class Ret, class Type1, class Parm1, class Parm2> 
Functor* DeferCall2(const CalleePtr& pCallee, Ret (Callee::*pFunction)(Type1, Type1), const Parm1& rParm1, 
        const Parm2& rParm2) { 
    return new MemberFunctor2<CalleePtr, Ret (Callee::*)(Type1, Type1), Parm1, Parm2>(pCallee, pFunction, rParm1, rParm2); 
} 

的变化是在这里:

Ret (Callee::*pFunction)(Type1, Type1) 
           ^^^^^^^ 

出现的两个地方或者如果第二个类型不总是与第一个类型相同,则添加另一个模板参数。

主叫仿函数有两个整数:void (TestObj::*)(int, int)

要调用:

DeferCall2(this, &TestObj::test2, 3, 3); 

其中&TestObj::test2具有类型void (TestObject::*)(int, int)。的DeferCall2的签名具有不必要的许多模板的参数,但它需要的第二个参数的类型是:

Ret(Callee::*pFunction)(Type1) 

也就是说,一个指向非CV-合格的,非可变参数构件函数,它一个参数。因此扣除失败。你错过了第二种类型。


注意,你只是有效地重新实现std::bind

auto call3 = std::bind(this, &TestObj::test2, 3, 3); 
call3();