C++ 下 Function 对象的实现(下)

2014-11-24 12:59:15 · 作者: · 浏览: 0

上篇中,我们实现了一个支持 R () 型函数的 Function。补充说明一下,在我们对成员函数的支持中,我们是这样定义的:

template
class MemberFunction0 : public FunctionBase0
{

private:
R (T::*m_pMemFun)();
T *m_pObj;
};

Loki 特意在著作中提醒我们,这里的 T 最好不要是函数类型,改为函数指针类型,如此该类的支持范围将扩大。如下:

template
class MemberFunction0 : public FunctionBase0
{
public:
R Invoke()
{
return (m_pObj->*m_pMemFun)();
}

public:
MemberFunction0(P pObj, R (T::*pMemFun)())
: m_pObj(pObj), m_pMemFun(pMemFun)
{

}

private:
R (T::*m_pMemFun)();
P m_pObj;
};

于是,P 和 T 的关系不那么紧密了,P 不一定非要 T* 不可,也可以是诸如 SmartPtr 之类的玩意儿。原本只支持传入一个对象和该对象的成员函数的,现在变成传入一个具有指针概念的东东和一个成员函数,只要这个“指针”使用运算符 > 去调用那个成员函数合乎语法即可。

接下来,我们来扩展这个 Function,以支持拥有数目在给定上限内的任意参数的函数。

我们先来手工写一下,看看如何支持带一个参数的函数。首先定义一个虚基类:

template
class FunctionBase1
{
public:
virtual R Invoke(T0) = 0;
virtual ~FunctionBase1() {}
};

实现两个版本,分别支持非成员函数和成员函数:

template
class Function1 : public FunctionBase1
{
public:
R Invoke(T0 v0)
{
return m_Fun(v0);
}

public:
Function1(const T &fun)
: m_Fun(fun)
{

}

private:
T m_Fun;
};

template
class MemberFunction1 : public FunctionBase1
{
public:
R Invoke(T0 v0)
{
return (m_pObj->*m_pMemFun)(v0);
}

public:
MemberFunction1(P pObj, R (T::*pMemFun)(T0))
: m_pObj(pObj), m_pMemFun(pMemFun)
{

}

private:
R (T::*m_pMemFun)(T0);
P m_pObj;
};

增加一个函数引用萃取的偏特化版本:

template
struct FunctionTraits
{
typedef RetType (&ParamType)(T0);
};

增加一个 Function 类的偏特化版本:

template
class Function
{
public:
template
Function(const T &fun)
: m_pFunBase(new Function1::ParamType>(fun))
{

}

template
Function(P pObj, R (T::*pMemFun)(T0))
: m_pFunBase(new MemberFunction1(pObj, pMemFun))
{

}

~Function()
{
delete m_pFunBase;
}

R operator ()(T0 v0)
{
return m_pFunBase->Invoke(v0);
}

private:
FunctionBase1 *m_pFunBase;
};

现在,我们可以跑一下测试代码了:

Function f1(&intfun1);
Function f1_(intfun1);
Function f2(intfunctor1);
Function f3(&test, &Test::intmem1);

f1(1);
f1_(1);
f2(2);
f3(3);

当然,void 函数也是支持的。

观察上面的这些代码,和我们在上一篇中的代码高度一致,不同的是那些模版参数、偏特化参数、函数调用参数等地方。

假如有这么一组宏:
TYPENAME_DECLARE(n) 被定义为 typename T0, typename T1, …, typename Tn
TYPENAME_LIST(n) 被定义为 T0, T1, …, Tn
TYPENAME_VARIABLE(n) 被定义为 T0 v0, T1 v1, …, Tn vn
VARIABLE_LIST(n) 被定义为 v0, v1, …, vn

那么我们可以使用一个 n 就写出支持所有具有参数的函数的 Function 了。我们抛弃掉上面的 1 系列的所有类,仅保持上篇留下来的代码,然后利用上面 4 个宏将所有数字尾巴去掉,于是代码变成:

template
class FunctionBase_##n
{
public:
virtual R Invoke(TYPENAME_LIST(n)) = 0;
virtual ~FunctionBase_##n() {}
};


template
class Function_##n : public FunctionBase_##n
{
public:
R Invoke(TYPENAME_VARIABLE(n))
{
return m_Fun(VARIABLE_LIST(n));
}

public:
Function_##n(const T &fun)
: m_Fun(fun)
{

}

private:
T m_Fun;
};

template
class MemberFunction_##n : public FunctionBase_##n
{
public:
R Invoke(TYPENAME_VARIABLE(n))
{
return (m_pObj->*m_pMemFun)(VARIABLE_LIST(n));
}

public:
MemberFunction_##n(P pObj, R (T::*pMemFun)(TYPENAME_LIST(n)))
: m_pObj(pObj), m_pMemFun(pMemFun)
{

}

private:
R (T::*m_pMemFun)(TYPENAME_LIST(n));
P m_pObj;
};

template
struct FunctionTraits
{
typedef RetType (&ParamType)(TYPENAME_LIST(n));
};

template
class Function
{
public:
template
Function(const T &f