C++ C++;类工厂宏
我想制作一个宏来轻松创建新类,这些新类派生自具有不同名称和稍有不同行为的相同基类 我已经有了C++ C++;类工厂宏,c++,macros,c-preprocessor,factory,C++,Macros,C Preprocessor,Factory,我想制作一个宏来轻松创建新类,这些新类派生自具有不同名称和稍有不同行为的相同基类 我已经有了 class FactoryBonusModifier { public: /// Function to overload virtual BonusModifierAbstract* createBonus() const = 0; protected: }; #define DEFAULT_BONUS_FACTORY_DECLARATION(FactoryName) \ cl
class FactoryBonusModifier
{
public:
/// Function to overload
virtual BonusModifierAbstract* createBonus() const = 0;
protected:
};
#define DEFAULT_BONUS_FACTORY_DECLARATION(FactoryName) \
class Factory## FactoryName : public FactoryBonusModifier \
{ \
public: \
virtual BonusModifierAbstract* createBonus() const; \
};
#define DEFAULT_BONUS_FACTORY_IMPLEMENTATION(FactoryName) \
BonusModifierAbstract* Factory## FactoryName::createBonus() const \
{ return new FactoryName(); }
DEFAULT_BONUS_FACTORY_DECLARATION(BonusModifierGoThroughWall);
以及cpp中编写的实现部分
我想知道我是否可以有一个宏,它可以用尽可能少的复制/粘贴来构建一个枚举和这些新类的数组
最后我想要的是
enum BonusType{
Bonus1,
Bonus2,
...,
Nb_Bonus
};
FactoryBonusModifier* factories[Nb_Bonus] =
{
new FactoryBonus1(),
new FactoryBonus2(),
...,
}
bonuses = ["BonusModifierGoThroughWall", "SomeOtherBonus" ];
print "enum BonusType {"
for x in bonuses:
print "t"+x+","
print "nBonusTypes"
print "};"
print "FactoryBonusModifier* factories["+len(bonuses)+"] = {"
for x in bonuses:
print "new Factory<"+bonus+">(),"
print "};"
如果可以避免的话,我会避免使用宏。我会改用模板
class FactoryBonusModifier
{
public:
/// Function to overload
virtual BonusModifierAbstract* createBonus() const = 0;
protected:
};
template<typename Bonus>
class Factory : public FactoryBonusModifier
{
public:
virtual Bonus* createBonus() const
{
return new Bonus();
}
}
类FactoryBonusModifier
{
公众:
///函数过载
虚拟BonusModifierAbstract*createBonus()常量=0;
受保护的:
};
模板
类工厂:公共工厂BonusModifier
{
公众:
虚拟奖金*createBonus()常量
{
返还新奖金();
}
}
因此,棘手的一点是创建枚举和工厂列表。为此,我将生成代码,而不是尝试使用模板。您可以非常轻松地将代码生成集成到大多数构建过程中。。但你需要仔细阅读
我个人会使用一个非常简单的python脚本,比如
enum BonusType{
Bonus1,
Bonus2,
...,
Nb_Bonus
};
FactoryBonusModifier* factories[Nb_Bonus] =
{
new FactoryBonus1(),
new FactoryBonus2(),
...,
}
bonuses = ["BonusModifierGoThroughWall", "SomeOtherBonus" ];
print "enum BonusType {"
for x in bonuses:
print "t"+x+","
print "nBonusTypes"
print "};"
print "FactoryBonusModifier* factories["+len(bonuses)+"] = {"
for x in bonuses:
print "new Factory<"+bonus+">(),"
print "};"
bonus=[“BonusModifierGoThroughWall”,“SomeOtherBonus”];
打印“枚举BonuType{”
对于奖金中的x:
打印“t”+x+”,“
打印“nBonusTypes”
打印“};”
打印“FactoryBonusModifier*工厂[”+len(奖金)+“]={”
对于奖金中的x:
打印“新工厂(),”
打印“};”
应输出:
enum BonusType {
tBonusModifierGoThroughWall,
tSomeOtherBonus,
nBonusTypes
};
FactoryBonusModifier* factories[2] = {
new Factory<BonusModifierGoThroughWall>(),
new Factory<SomeOtherBonus>(),
};
枚举BonuType{
TBONU烟雾机,
tSomeOtherBonus,
布努斯泰普斯酒店
};
FactoryBonusModifier*工厂[2]={
新工厂(),
新工厂(),
};
这是对@MichaelAnderson解决方案的扩充
执行相同的FactoryBonusModifier
,但不要在python中生成enum
和数组。在模板元编程中实现
首先,一些样板。这只是一个模板元编程工具包:
template<typename...>
struct type_list {};
// get the nth type from a list:
template<int n, typename list>
struct nth_type;
// the 0th type is the first type:
template<0, typename t0, typename... types>
struct nth_type<0, type_list<t0,types...>> {
typedef t0 type;
};
// the nth type is the n-1th type of the tail of the list:
template<int n, typename t0, typename... types>
struct nth_type<n, type_list<t0,types...>>:nth_type<n-1,type_list<types...>>
{};
// Get the index of T in the list. 3rd parameter is for metaprogramming.
template<typename T, typename list, typename=void>
struct index_in;
// If T is the first type in the list, the index is 0
template<typename T, typename t0, typename... list>
struct index_in<T, type_list<t0, list...>, typename std::enable_if<std::is_same<T,t0>::value>::type> {
enum {value = 0};
};
// If T is not the first type in the list, the index is 1 plus the index of T
// in the tail of the list:
template<typename T, typename t0, typename... list>
struct index_in<T, type_list<t0, list...>, typename std::enable_if<!std::is_same<T,t0>::value>::type> {
enum {value = index_in<T, type_list<list...>>::value+1};
};
// calls () on the arguments passed to it in order:
inline void do_in_order() {}
template<typename L0, typename... Lambdas>
void do_in_order( L0&& l0, Lambdas&&... lambdas ) {
std::forward<L0>(l0)(); // std::forward is for insane corner cases, not usually needed
do_in_order( std::forward<Lambdas>(lambdas)... );
}
到目前为止什么也没做。加上迈克尔的回答:
class FactoryBonusModifier
{
public:
/// Function to overload
virtual BonusModifierAbstract* createBonus() const = 0;
protected:
};
template<typename Bonus>
class Factory : public FactoryBonusModifier
{
public:
virtual Bonus* createBonus() const
{
return new Bonus();
}
};
我们完成了
MetaFactory_t::Enum
是一种表示单个工厂及其在数组中的偏移量的类型。要获取给定奖金类型的Enum
值,MetaFactory\u t::GetIndex()
提供了该值
如果希望工厂用于给定的奖金类型,MetaFactory.GetItem()
将返回一个正确类型的指针,指向factory
。如果有Enum
值n
,则元工厂.GetItem(n)
返回指向FactoryBonusModifier
基类的指针(如果n
超出范围,则返回nullptr
)
工厂生存期由元工厂
对象的生存期管理
简言之,在使用模板之前,代码生成通常用于这类事情。但是变量模板使得整型
类型映射非常容易,并且允许相当可观的代码生成
作为附带的好处,这个版本包含了许多python生成的版本所没有的类型安全性。我甚至可以编写一个函数,它接受n
,调用一个传入的functor,并带有指向所讨论工厂的适当类型的指针,从而生成更多的类型安全性
现在,如果您有超过100种额外类型,那么这种技术会变得更加困难,因为编译器递归限制会受到影响。即使如此,也有一些技术允许以这种方式处理1000种类型的列表(然而,它们更难处理)
上面的代码还没有编译过,所以几乎肯定包含bug,但基本设计是可靠的——我以前做过这件事。在模板之前,宏经常用于这类事情,这很有趣。我不会说这是严格重复的,因为这特别(至少部分)涉及到为此目的使用宏,而另一个问题则不然。