我想实现一个用于创建对象的工厂函数。我的对象模板如下所示:
template <typename TA, typename TB>
struct MyImpl : public MyInterface
{
// content
};我的工厂是这样的:
MyInterface* factory(char ta, char tb)
{
if(ta == 'c' && tb == 'c')
{
return new MyImpl<char, char>();
}
if(ta == 'c' && tb == 's')
{
return new MyImpl<char, short>();
}
if(ta == 's' && tb == 'c')
{
return new MyImpl<short, char>();
}
// and so on ....
}工厂函数必须接受非静态char数据(ta,tb),因为它不能在编译时确定,我认为这就是这个工厂的全部要点。实际上,ta和tb是从文件(或网络)中读取的。
我想要一个更简单的解决方案,以避免烦人的2级开关。
我认为我的问题与how-would-one-write-a-meta-if-else-if-in-c类似,但我不能使用静态参数。
也许我应该回到C宏,并使用一些宏技巧来收缩我的当前代码?
提前感谢!
更新
回复@Rob:
我的实际代码将更复杂,其中有许多其他东西,更难阅读和不相关的许多方面。我正在尝试正确的伪码,如果有任何问题,请告诉我:-)。
答复@Dynguss:
我的问题是,在我的实际实现中,工厂( ta,tb)的参数范围很大,比如10×ta和20×tb,而ta和tb的组合将是很长的线,而且很难维护。所以我至少需要一些方法来缓解这种结合的努力。
发布于 2012-09-24 14:02:16
以下是一个想法:
template <typename T>
MyInterface * factroy(char t)
{
if (t == 'c') { return MyImpl<T, char>(); }
if (t == 's') { return MyImpl<T, short>(); }
// ...
}
MyInterface * factory(char ta, char tb)
{
if (ta == 'c') { return factroy<char>(tb); }
if (ta == 's') { return factroy<short>(tb); }
// ...
}使用各种模板,可以将此模式扩展到任意数量的类型参数--例如:
struct Base { virtual ~Base() = default; };
template <typename A, typename B, typename C> struct Foo : Base { };
#include <tuple>
template <typename ...Args>
constexpr Base * factory(std::tuple<Args...>)
{
return new Foo<Args...>;
}
template <typename ...Args, typename ...Char>
constexpr Base * factory(std::tuple<Args...>, char t, Char ... ts)
{
return t == 'c' ? make(std::tuple<char, Args...>(), ts...)
: t == 's' ? make(std::tuple<short int, Args...>(), ts...)
: t == 'i' ? make(std::tuple<int, Args...>(), ts...)
: t == 'l' ? make(std::tuple<long int, Args...>(), ts...)
: nullptr;
}用法:auto p = factory(std::tuple<>(), 'c', 's', 'l');
发布于 2012-09-24 15:02:04
如果您可以将Impl构造函数分离为新的Impl(新InnerImpl),那么就有可能找到一个非常复杂的解决方案,用一个映射来代替开关:
struct Creator {
virtual ~Creator(){};
virtual Interface *create(InterfaceInner *) = 0;
virtual InterfaceInner *createInner() = 0;
}
std::Map<char, Creator *> creatorMap;
template<char T>
struct Factory {
Factory() {
creatorMap.insert(T, &this->creator);
}
}
template<>
struct Factory<'s'> {
struct ShortCreator : public Creator {
virtual Interface *create(InterfaceInner *inner) {return new Impl<short>(inner);}
virtual InterfaceInner *createInner(return new ImplInner<short>());
} creator;
}
Factory<'s'> shortFactory;
Factory<'c'> charFactory;
creatorMap[ta].create(creatorMap[tb].createInner());发布于 2012-09-24 15:59:26
那麽:
MyInterface* factory(char ta, char tb)
{
switch( ta << 8 | tb )
{
case 'cc': return MyImpl<char, char>();
case 'cs': return MyImpl<char, short>();
case 'sc': return MyImpl<short, char>();
// and so on ....
}
}注意:这在英特尔/AMD x86和x64上工作得很好,在具有不同功能的CPU上(例如PPC),您必须像这样交换ta和tb:switch( ta | tb << 8 )。
https://stackoverflow.com/questions/12566271
复制相似问题