【问题标题】:Static dispatch over multiple types using templates or a macro使用模板或宏对多种类型进行静态调度
【发布时间】:2014-05-26 06:14:02
【问题描述】:

我目前正在重构一些代码,我希望 SO 可以帮助我找到一种巧妙的方法,将大量样板代码简化为几个简单的方法。我的问题类似于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 是否有另一个想法,即我如何使用模板或可能的宏以更好的方式构造它。 (因为我担心类型系统会妨碍任何模板化解决方案。)

干杯 阿斯格

【问题讨论】:

  • 为什么这个问题用 CUDA 标记?这实际上是您在此处编写的 GPU 代码吗?
  • “不支持虚拟方法” - wat
  • @mattmcnabb 那是因为这实际上是 CUDA C 而不是标准 C++。 CUDA 不支持虚函数或从基类继承虚函数作为参数传递给 GPU 函数
  • 我想我现在可以回答你之前的问题了
  • index 是否需要作为运行时值,或者您可以将其设为模板参数吗?

标签: c++ templates macros


【解决方案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;
}

【讨论】:

  • 抱歉回复太晚了。这似乎解决了一个不同的问题,因为现在索引已经消失了。对我来说非常重要的是,我可以索引到我的组件列表并且隐藏第 i 个组件的实际类型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-18
  • 2013-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多