Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/165.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;类工厂宏_C++_Macros_C Preprocessor_Factory - Fatal编程技术网

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,但基本设计是可靠的——我以前做过这件事。

在模板之前,宏经常用于这类事情,这很有趣。我不会说这是严格重复的,因为这特别(至少部分)涉及到为此目的使用宏,而另一个问题则不然。