如何在数组或向量中使用不同的 functoid

How to use different functoids within an array or vector

我编写了一小段代码,可以使用 mem_fun 模板调用包含在 functoid 中的 setter 和 getter 函数。

我现在想在 class 层次结构之上使用这种方法,其中每个 class 可能有 getter 和 setter 可以在其中注册为对如果需要,可以调用 getter 和 setter 的向量或数组。 GUIObject 和 GUICompositeObject 是描述的 class 层次结构中的示例 classes。 不幸的是,对象的 bound_mem_fun_t 具有不同的类型,这就是我不知道如何将它们集成到指向函子的 array/vector 指针的原因。

在 c++11 中我会使用 std::function。有没有办法在 c++98 中模拟这个?

因为我们的编译器只支持c++98,所以不能使用c++11或者c++14的新特性。也不允许提升。

#include <functional>

class GUIObject
{
    int m_Alpha;
public:
    void SetAlpha(int a) { m_Alpha = a;};
    int GetAlpha() {return m_Alpha;};
};


class GUICompositeObject: public GUIObject
{
    int m_NumOfChilds;
public:
    void SetNumOfChilds(int NumOfChilds) { m_NumOfChilds = NumOfChilds;};
    int GetNumOfChilds() {return m_NumOfChilds;};
};

template<typename T>
struct bound_mem_fun_t 
{ 
    bound_mem_fun_t(std::mem_fun_t<int, T> GetFunc, std::mem_fun1_t<void, T, int> SetFunc, T* o) :
            m_GetFunc(GetFunc), m_SetFunc(SetFunc), obj(o) { } ;
    int operator()() { return m_GetFunc(obj); } ;
    void operator()(int i) { m_SetFunc(obj, i); } ;
    std::mem_fun_t<int, T> m_GetFunc; 
    std::mem_fun1_t<void, T, int> m_SetFunc; 
    T* obj; 
};


int main()
{
    GUIObject kGUIObject;
    GUICompositeObject kCompObj;

    bound_mem_fun_t<GUIObject> GUIObjectFunc(std::mem_fun(&GUIObject::GetAlpha), std::mem_fun(&GUIObject::SetAlpha), &kGUIObject);
    GUIObjectFunc(17);
    int ii = GUIObjectFunc();

    bound_mem_fun_t<GUICompositeObject> GUICompObjectFunc(std::mem_fun(&GUICompositeObject::GetNumOfChilds), std::mem_fun(&GUICompositeObject::SetNumOfChilds), &kCompObj);
    GUICompObjectFunc(17);
    int iChilds = GUICompObjectFunc();

    return 0;
}

这是@filmors 回答后的完整解决方案:

#include <functional>
#include <vector>
#include <iostream>

class GUIObject
{
    int m_Alpha;
public:
    void SetAlpha(int a) { m_Alpha = a;};
    int GetAlpha() {return m_Alpha;};
};


class GUICompositeObject: public GUIObject
{
    int m_NumOfChilds;
public:
    void SetNumOfChilds(int NumOfChilds) { m_NumOfChilds = NumOfChilds;};
    int GetNumOfChilds() {return m_NumOfChilds;};
};

struct bound_mem_fun_base 
{
    virtual int operator()() =0;
    virtual void operator()(int) =0;
};

template<typename T>
struct bound_mem_fun_t : public bound_mem_fun_base
{ 
    bound_mem_fun_t(std::mem_fun_t<int, T> GetFunc, std::mem_fun1_t<void, T, int> SetFunc, T* o) :
            m_GetFunc(GetFunc), m_SetFunc(SetFunc), obj(o) { } ;
    virtual int operator()() { return m_GetFunc(obj); } ;
    virtual void operator()(int i) { m_SetFunc(obj, i); } ;
    std::mem_fun_t<int, T> m_GetFunc; 
    std::mem_fun1_t<void, T, int> m_SetFunc; 
    T* obj; 
};

template<typename T> bound_mem_fun_t<T>* make_setter(std::mem_fun_t<int, T> GetFunc, std::mem_fun1_t<void, T, int> SetFunc, T* o)
{
    return new bound_mem_fun_t<T> (GetFunc, SetFunc, o);
}

int main()
{
    GUIObject kGUIObject;
    GUICompositeObject kCompObj;

    std::vector<bound_mem_fun_base*> kBoundVector;

    kBoundVector.push_back(new bound_mem_fun_t<GUIObject> (std::mem_fun(&GUIObject::GetAlpha), std::mem_fun(&GUIObject::SetAlpha), &kGUIObject));
    kBoundVector.push_back(new bound_mem_fun_t<GUICompositeObject> (std::mem_fun(&GUICompositeObject::GetNumOfChilds), std::mem_fun(&GUICompositeObject::SetNumOfChilds), &kCompObj));
    kBoundVector.push_back(make_setter<GUIObject> (std::mem_fun(&GUIObject::GetAlpha), std::mem_fun(&GUIObject::SetAlpha), &kGUIObject));
    kBoundVector.push_back(make_setter<GUICompositeObject> (std::mem_fun(&GUICompositeObject::GetNumOfChilds), std::mem_fun(&GUICompositeObject::SetNumOfChilds), &kCompObj));

    for (int i = 0; i < 4 ; i++)
    {
        (*kBoundVector[i])(i*10);
        int res = (*kBoundVector[i])();
        std::cout << "Getter result " << res << "\n";
    }

    return 0;
}

不幸的是,make_setter 函数并没有真正缩短函子的创建时间。欢迎任何想法。

只要给你的 bound_mem_fun_t<T> 一个公共基础 class 并使用动态调度来解决你的问题:

struct bound_mem_fun_base {
    virtual int operator()() = 0;
    virtual void operator()(int) = 0;
};

template <typename T>
struct bound_mem_fun_t : bound_mem_fun_t ...

然后您可以在向量中保留指向 bound_mem_fun_base 的指针,并将元素称为 (*v[0])()

此外,TR1 确实包含 std::tr1::function,是否可用?

首先是来自 c++11 的关于 std::function 的评论:这不会解决您的问题,因为您需要一个已经有界的函数指针。该指针必须绑定到您的对象。我相信您需要的是 std::bind.

自己的实现

我只开始了一个很! small Binder class 希望它能满足您的需求。如果你需要在旧的 c++ 版本中有模板参数列表,请查看 lokihttp://loki-lib.sourceforge.net/

作为提示,我可以给你一个简短的例子来说明我做了什么:

class A
{   
    private:
        int val;
    public:
        A(int i): val(i) {}  
        void Do(int i) { std::cout << "A " << val<< " " << i << std::endl; }
};  

class B
{   
    private:
        int val;
    public:
        B(int i): val(i){}
        void Go(int i) { std::cout << "B " << val << " " << i << std::endl; }
};  

class Base
{   
    public:
        virtual void operator()(int i)=0; 
};  

template <typename T>
class Binder: public Base
{   
    void (T::*fnct)(int);
    T* obj;

    public:
    Binder( void(T::*_fnct)(int), T*_obj):fnct(_fnct),obj(_obj){}  
    void operator()(int i)
    {   
        (obj->*fnct)(i);
    }   

};  

int main()
{   
    A a(100);
    B b(200);

    // c++11 usage for this example
    //std::function<void(int)> af=  std::bind( &A::Do, &a, std::placeholders::_1);
    //af(1);

    // hand crafted solution
    Base* actions[2];

    actions[0]= new Binder<A>( &A::Do, &a);
    actions[1]= new Binder<B>( &B::Go, &b);

    actions[0]->operator()(55);
    actions[1]->operator()(77);

}