使用模板或宏在多种类型上进行静态分派

时间:2014-05-26 06:14:03

标签: c++ templates macros

我正在重构一些代码,我希望这可以帮助我找出一种巧妙的方法,将一些样板减少到一些简单的方法。我的问题类似于C++ function dispatch with template parameters

基本上我有几个类(目前为止7个)都符合相同的模板化接口,但由于不支持虚拟方法,所以不会从任何常见的超类继承。

让我们说界面是

template<typename T> class IComponent : public T {
    int Food() { return T::Food(); }
    bool FooBarred() { return T::FooBarred(); }
};

然后我有两个符合该接口的类

class ComponentA {
    int Food() { return 42; }
    bool FooBarred() { return false; }
};

class ComponentB {
    int Food() { return 5; }
    bool FooBarred() { return true; }
};

然后我在许多合成类中以任意方式组合这些组件(目前我有12个),它们看起来像这样。

class MultiComponent {
    ComponentA cA;
    ComponentB cB;
    ComponentC cC;

    int NumComponents() { return 2; }
    int Food(index i) { 
        if (i == 0)
            return cA.Food();
        else if (i == 1)
            return cB.Food();
        else // if (i == 2)
            return cC.Food();
    }
    bool FooBarred(index i) {
        if (i == 0)
            return cA.FooBarred();
        else if (i == 1)
            return cB.FooBarred();
        else // if (i == 2)
            return cC.FooBarred();
    }
};

有7个组件类从接口实现9个方法,并由12个不同的包装器组合(到目前为止),这个代码库几乎只会爆炸,只能使用一堆if进行动态调度。

我希望将其减少为某种聪明的调度员

template <typename RetVal, typename C>
RetVal ApplyTo(int index, RetVal(*fn)(const C* component)) {
    if (index == 0)
        return fn(cA);
    else if (index == 1)
        return fn(cB);
    else
        return fn(cC);
}

我可以用来将运算符应用于第i个组件,这样我只需要为每个复合类实现一次ApplyTo,我就可以通过访问我的组件及其所有方法和属性了这种方法。

以任何可能的方式做这样的事情吗?或者SO是否有另外的想法,我可以用模板或宏可能以更好的方式构建它。 (因为我担心类型系统会妨碍任何模板解决方案。)

干杯 导演Asger

1 个答案:

答案 0 :(得分:1)

我尝试了一些东西,看看你想要如何概括代码:

#include <iostream>

template<typename T> 
class IComponent : public T {
  public:
    int Food() { return T::Food(); }
    bool FooBarred() { return T::FooBarred(); }
};

class ComponentA{
  public:
    int Food() { return 42; }
    bool FooBarred() { return false; }
};

class ComponentB{
  public:

    int Food() { return 5; }
    bool FooBarred() { return true; }
};

class ComponentC{
  public:

    int Food() { return 6; }
    bool FooBarred() { return true; }
};

//An example WRAPPER class
class MultiComponent {

    public:

    int NumComponents() { return 2; }

    template<typename T>
    bool foo(IComponent<T>* object)
    {
        object->Food();
        return object->FooBarred();
    }
};

//Routes calls to specific instance of components via wrapper object
template <typename RetVal, typename C, typename Wrapper, typename Func>
RetVal ApplyTo(Func func, Wrapper& wrapper )
{
   IComponent<C> obj;
   return (wrapper.*func)(&obj);  
}
//wrapper call backs
typedef bool (MultiComponent::*CallBackC)(IComponent<ComponentC>*);

typedef bool (MultiComponent::*CallBackA)(IComponent<ComponentA>*);

typedef bool (MultiComponent::*CallBackB)(IComponent<ComponentB>*);

int main()
{   
   MultiComponent wrapper;
   //call Component C
   CallBackC callback;
   callback = &MultiComponent::foo<ComponentC> ;

   bool result = ApplyTo<bool, ComponentC, MultiComponent, CallBackC>(callback, wrapper);

   std::cout<<"Result of C "<<result<<std::endl;

   //call Component A
   CallBackA callbackA;
   callbackA = &MultiComponent::foo<ComponentA> ;

   result = ApplyTo<bool, ComponentA, MultiComponent, CallBackA>(callbackA, wrapper);

   std::cout<<"Result of A "<<result<<std::endl;

   return 0;
}