2016-03-04 161 views
0

我有一個情況(在嵌入式系統上),我想從另一個任務調用函數。我發現這種方法是這樣做的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; 
} 

回答

1

你忘了在函數的第二個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)

0

要調用:

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();