我在我的服务器一个结构,我想在C宏或模板来生成它++,因为它有很多冗余的东西:
struct MyBlock {
void Merge(const MyBlock& from) {
if (apple.HasData()) {
apple.Merge(from.apple);
}
if (banana.HasData()) {
banana.Merge(from.banana());
}
...
}
void Clear() {
apple.Clear();
banana.Clear();
...
}
void Update(const SimpleBlock& simple_block) {
if (simple_block.apple.Updated()) {
apple.Add(simple_block.apple);
}
if (simple_block.banana.Updated()) {
banana.Add(simple_block.banana);
}
...
}
Fruit apple;
Fruit banana;
Animal dog;
Animal cat;
...
}
struct SimpleBlock {
SimpleFruit apple;
SimpleFruit banana;
SimpleAnimal dog;
SimpleAnimal cat;
...;
}
我想在像苹果和狗两大块来定义多个变量。 我也想定义更多对这样的块。 但它涉及到很多琐碎的工作。 所以我的问题是我们如何使用宏,模板或其他一些C ++功能,包括C ++ 11来生成编译时这些块?
我为什么不使用集合来存储这些变量的原因是因为MyBlock结构会在另外一个模板类,它会动态地分配和释放在运行时该块参数传递。 它实际上是一个线程局部块将定期汇总。
与预处理程序列表进行迭代足够简单:
#define M_NARGS(...) M_NARGS_(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define M_NARGS_(_10, _9, _8, _7, _6, _5, _4, _3, _2, _1, N, ...) N
#define M_CONC(A, B) M_CONC_(A, B)
#define M_CONC_(A, B) A##B
#define M_ID(...) __VA_ARGS__
#define M_LEFT(L, R) L
#define M_RIGHT(L, R) R
#define M_FOR_EACH(ACTN, ...) M_CONC(M_FOR_EACH_, M_NARGS(__VA_ARGS__)) (ACTN, __VA_ARGS__)
#define M_FOR_EACH_0(ACTN, E) E
#define M_FOR_EACH_1(ACTN, E) ACTN(E)
#define M_FOR_EACH_2(ACTN, E, ...) ACTN(E) M_FOR_EACH_1(ACTN, __VA_ARGS__)
#define M_FOR_EACH_3(ACTN, E, ...) ACTN(E) M_FOR_EACH_2(ACTN, __VA_ARGS__)
#define M_FOR_EACH_4(ACTN, E, ...) ACTN(E) M_FOR_EACH_3(ACTN, __VA_ARGS__)
#define M_FOR_EACH_5(ACTN, E, ...) ACTN(E) M_FOR_EACH_4(ACTN, __VA_ARGS__)
//.. extend this to higher numbers with some copy&paste
#define MYBLOCK(...) struct MyBlock { \
void Merge(const MyBlock& from) { \
M_FOR_EACH(BLOCK_MERGE, __VA_ARGS__) \
} \
void Clear() { \
M_FOR_EACH(BLOCK_CLEAR, __VA_ARGS__) \
} \
void Update(const SimpleBlock& simple_block) { \
M_FOR_EACH(BLOCK_UPDATE, __VA_ARGS__) \
} \
M_FOR_EACH(BLOCK_FIELD, __VA_ARGS__) \
}
#define BLOCK_MERGE(F) if (M_ID(M_RIGHT F).HasData()) { \
M_ID(M_RIGHT F).Merge(from.M_ID(M_RIGHT F)); \
}
#define BLOCK_CLEAR(F) M_ID(M_RIGHT F).Clear;
#define BLOCK_UPDATE(F) if (simple_block.M_ID(M_RIGHT F).Updated()) { \
M_ID(M_RIGHT F).Add(simple_block.M_ID(M_RIGHT F)); \
}
#define BLOCK_FIELD(F) M_ID(M_LEFT F) M_ID(M_RIGHT F);
#define SIMPLEBLOCK(...) struct SimpleBlock { M_FOR_EACH(SIMPLE_DECL, __VA_ARGS__) }
#define SIMPLE_DECL(F) M_CONC(Simple, M_ID(M_LEFT F)) M_ID(M_RIGHT F);
#define FIELDS (Fruit, apple),(Fruit,banana),(Animal,dog),(Animal,cat)
MYBLOCK(FIELDS);
SIMPLEBLOCK(FIELDS);
添加必要的进一步成员变量FIELDS
在现有格式中,并且它们将被添加到由所发射的结构MYBLOCK
和SIMPLEBLOCK
。 (记住延长M_FOR_EACH
与更多的迭代...容易一些CTRL + C,Ctrl + V将到。)
template <typename SimpleT>
class BlockTemplate
{
public:
void Merge(const BlockTemplate& from) {
if (HasData()) {
Merge(from.simpleData);
}
}
void Update(const SimpleT& simple_block) {
if (simple_block.Updated()) {
Add(simple_block.data);
}
}
protected:
SimpleT simpleData;
};
现在,您可以创建类型的对象BlockTemplate<SimpleFruit>
BlockTemplate<SimpleAnimal>
等,还可以存储指向所有这些BlockTemplate
在一个容器中的对象有BlockTemplate从抽象类型继承后。 或者,更好的是,使用新一届类型擦除方法- boost::type_erasure::any
的例子。
编辑:如果你不想使用容器这样一来,你也可以让BlockTemplate
可变参数和存储不同的(类型形式)的元组SimpleT
对象和修改Merge
和Update
相应的功能。 这里的问题是,它变得更难跟踪SimpleT
对象- std::tuple
不允许你给的名字。 你会参照值get<N>(tupleData)
你为什么不使用收集的描述听起来像一些优化的事情。 你已经测量?
无论如何,一个简单的解决方案是将指针存储到一个集合中的对象。
然后你就可以在访问集合。