带有附加arg的C ++模板问题

时间:2016-03-04 14:07:17

标签: c++ templates

我有一种情况(在嵌入式系统上),我希望从另一个任务调用函数。我找到了这种方法http://www.drdobbs.com/elegant-function-call-wrappers/184401385。但是我有更多的论据要做什么。最好的情况我有一个解决方案,这是在模板中,但我不知道如何实现这一点。无论如何,还可以创建两个镜像,如下所示(在一个小型的Visual Studio C ++测试中)。除了给出编译时错误的DeferCall2调用外,一切正常。我在这里弄错了什么?

#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;
}

2 个答案:

答案 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)

答案 1 :(得分: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();