使用模板或宏对多个类型进行静态分派

Static dispatch over multiple types using templates or a macro

本文关键字:类型 分派 静态      更新时间:2023-10-16

我目前正在重构一些代码,我希望SO可以帮助我找出一个聪明的方法,将大量的样板文件减少到几个简单的方法中。我的问题类似于带有模板参数的c++函数分派。

基本上我有几个类(到目前为止有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有另一个想法,我如何能用模板或可能的宏以更好的方式构建这个。(因为我担心类型系统会妨碍任何模板化的解决方案。)

干杯asg

我已经尝试了一些东西,看看如果这是你想要泛化代码的方式:

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