我正在重构一些代码,我希望这可以帮助我找出一种巧妙的方法,将一些样板减少到一些简单的方法。我的问题类似于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
答案 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;
}