C ++复合模板类工厂
是否有可能在没有手动指定所有组合的情况下制作复合模板类工厂? 我的意思是,如果我有这些类:
class CompositeBase {};
template< typename C1, typename C2, typename C3 >
class Composite : public CompositeBase
{
private:
C1 component1;
C2 component2;
C3 component3;
};
class Component0 {}; //Also have Component1-9
我想创建一个这样的功能:
CompositeBase *CreateComposite(int c1, int c2, int c3);
以便
CreateComposite(4,3,7);
会创建并返回一个
Composite<Component4,Component3,Component7>
这样做的原因是我可以从文件加载数据并创建不同的组合对象。 该文件将具有用于创建每个复合对象的组件的三个值,然后是其所需的其他数据。
问题是有10个不同的组件,有1000个不同的可能的组合类。 要指定所有这些,将需要第一个组件的switch语句,第二个组件的10个switch语句以及这10个内的第三个组件的100个switch语句,并且该函数的长度为1000+行。
有没有其他方法来编写CreateComposite函数? 除了这个:
CompositeBase *CreateComposite(int c1, int c2, int c3)
{
switch(c1)
{
case 0:
switch( c2 )
{
case 0:
switch( c3 )
{
case 0: return new Composite<Component0,Component0,Component0>;
case 1: return new Composite<Component0,Component0,Component1>;
//etc
}
//etc
}
//etc
}
}
您可以通过使用级联模板方法在单个开关情况下避免O(n)的O(n ^ 3)复杂性:
#include <iostream>
using namespace std;
class CompositeBase
{
public:
virtual void print( std::ostream& o_out ) = 0;
};
template< typename C1, typename C2, typename C3 >
class Composite : public CompositeBase
{
public:
void print( std::ostream& o_out )
{
o_out << typeid(*this).name();
}
private:
C1 component1;
C2 component2;
C3 component3;
};
class Component0 {};
class Component1 {};
class Component2 {};
class Component3 {};
class Component4 {};
class Component5 {};
class Component6 {};
class Component7 {};
class Component8 {};
class Component9 {};
template<typename C1,typename C2,typename C3>
CompositeBase *CreateComposite0()
{
return new Composite<C1,C2,C3>();
}
template<typename C1,typename C2>
CompositeBase *CreateComposite1(int c3)
{
switch(c3)
{
case 0: return CreateComposite0<C1,C2,Component0>();
case 1: return CreateComposite0<C1,C2,Component1>();
case 2: return CreateComposite0<C1,C2,Component2>();
case 3: return CreateComposite0<C1,C2,Component3>();
case 4: return CreateComposite0<C1,C2,Component4>();
case 5: return CreateComposite0<C1,C2,Component5>();
case 6: return CreateComposite0<C1,C2,Component6>();
case 7: return CreateComposite0<C1,C2,Component7>();
case 8: return CreateComposite0<C1,C2,Component8>();
case 9: return CreateComposite0<C1,C2,Component9>();
default: return 0;
}
}
template<typename C1>
CompositeBase *CreateComposite2(int c2, int c3)
{
switch(c2)
{
case 0: return CreateComposite1<C1,Component0>(c3);
case 1: return CreateComposite1<C1,Component1>(c3);
case 2: return CreateComposite1<C1,Component2>(c3);
case 3: return CreateComposite1<C1,Component3>(c3);
case 4: return CreateComposite1<C1,Component4>(c3);
case 5: return CreateComposite1<C1,Component5>(c3);
case 6: return CreateComposite1<C1,Component6>(c3);
case 7: return CreateComposite1<C1,Component7>(c3);
case 8: return CreateComposite1<C1,Component8>(c3);
case 9: return CreateComposite1<C1,Component9>(c3);
default: return 0;
}
}
CompositeBase *CreateComposite(int c1,int c2, int c3)
{
switch(c1)
{
case 0: return CreateComposite2<Component0>(c2,c3);
case 1: return CreateComposite2<Component1>(c2,c3);
case 2: return CreateComposite2<Component2>(c2,c3);
case 3: return CreateComposite2<Component3>(c2,c3);
case 4: return CreateComposite2<Component4>(c2,c3);
case 5: return CreateComposite2<Component5>(c2,c3);
case 6: return CreateComposite2<Component6>(c2,c3);
case 7: return CreateComposite2<Component7>(c2,c3);
case 8: return CreateComposite2<Component8>(c2,c3);
case 9: return CreateComposite2<Component9>(c2,c3);
default: return 0;
}
}
int main()
{
CompositeBase* base1 = CreateComposite(4,5,6);
CompositeBase* base2 = CreateComposite(8,2,0);
base1->print(cout);
cout << endl;
base2->print(cout);
return 0;
}
只是为了好玩,你可以使用boost proprocessor来处理O(1)的复杂性
#include <iostream>
#include <boost/preprocessor/repetition.hpp>
using namespace std;
class CompositeBase
{
public:
virtual void print( std::ostream& o_out ) = 0;
};
template< typename C1, typename C2, typename C3 >
class Composite : public CompositeBase
{
public:
void print( std::ostream& o_out )
{
o_out << typeid(*this).name();
}
private:
C1 component1;
C2 component2;
C3 component3;
};
#define DIM 10
#define COMPONENT_DECLARATION(z,n,unused) class BOOST_PP_CAT(Component,n) {};
BOOST_PP_REPEAT(DIM,COMPONENT_DECLARATION, ~)
#undef COMPONENT_DECLARATION
template<typename C1,typename C2,typename C3>
CompositeBase *CreateComposite0()
{
return new Composite<C1,C2,C3>();
}
template<typename C1,typename C2>
CompositeBase *CreateComposite1(int c3)
{
#define COMPOSITE(z,n,unused) case n: return CreateComposite0<C1,C2,BOOST_PP_CAT(Component,n)>();
switch(c3)
{
BOOST_PP_REPEAT(DIM,COMPOSITE,~)
default: return 0;
}
#undef COMPOSITE
}
template<typename C1>
CompositeBase *CreateComposite2(int c2, int c3)
{
#define COMPOSITE(z,n,unused) case n: return CreateComposite1<C1,BOOST_PP_CAT(Component,n)>(c3);
switch(c2)
{
BOOST_PP_REPEAT(DIM,COMPOSITE,~)
default: return 0;
}
#undef COMPOSITE
}
CompositeBase *CreateComposite(int c1,int c2, int c3)
{
#define COMPOSITE(z,n,unused) case n: return CreateComposite2<BOOST_PP_CAT(Component,n)>(c2,c3);
switch(c1)
{
BOOST_PP_REPEAT(DIM,COMPOSITE,~)
default: return 0;
}
#undef COMPOSITE
}
#undef DIM
int main()
{
CompositeBase* base1 = CreateComposite(4,5,6);
CompositeBase* base2 = CreateComposite(8,2,0);
base1->print(cout);
cout << endl;
base2->print(cout);
return 0;
}
无论如何,如果可能的话,我建议尽量避免使用这些解决方案。
模板参数必须在编译时已知。 一个可能的解决方案是: CreateComposite<int, int, int>()
并且可以针对每种可能的情况对其进行专门化。 哦,那么:这是一个没有去..我建议你宁愿去与一些老式的动态多态和一个std::vector<ComponentBase>
。
在运行时无法生成模板的所有可能组合。 编译器需要知道你将使用哪一个,以便它可以为它们生成代码。
你有没有考虑过使用组合而不是继承?
编辑:通过作文我更多地思考以下内容:
class Composite
{
private:
ComponentBase * component1;
ComponentBase * component2;
ComponentBase * component3;
};
class Component0 : public ComponentBase {}; //Also have Component1-9
如果出于某种原因你不能使用指向基类的指针,那么你就被禁止有代码来生成所有模板类的排列。 但不是使用嵌套的case语句,你可以使用表来创建新的实例和宏,以使代码更容易。
typedef CompositeBase * NewComposite();
#define NEW_COMPOSITE(P1,P2,P3) CompositeBase * NewComposite##P1##P2##P3() { return new Composite<Component##P1,Component##P2,Component##P3>; }
NEW_COMPOSITE(0,0,0) NEW_COMPOSITE(0,0,1) NEW_COMPOSITE(0,0,2) NEW_COMPOSITE(0,0,3)
NEW_COMPOSITE(0,0,4) ...
...
CompositeBase *CreateComposite(int c1, int c2, int c3)
{
static NewComposite * newCompositeTable[10][10][10] = {{{NewComposite000,NewComposite001,...},{NewComposite010,...}}};
return newCompositeTable[c1][c2][c3]();
}
我真的不能说这是一个比你开始的更好的方法,但它是一个可以考虑的替代方案。
链接地址: http://www.djcxy.com/p/69063.html