【问题标题】:A group of variadic macros一组可变参数宏
【发布时间】:2014-12-22 07:42:28
【问题描述】:

我想将一组可变数量的参数传递给宏。我有以下不正确的宏:

#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__)

#define FRUITS (apple, banana, cherry)
#define ANIMALS (dog, monkey)

#define ZOO_BLOCK(NAME, FRTS, ANMLS) struct NAME##Block { \
  M_FOR_EACH(DEFINE_FRUITS, FRTS) \  // Wrong, see my question below
  M_FOR_EACH(DEFINE_ANIMAL, ANMLS) \  // Wrong
}

#define DEFINE_FRUITS(F) Fruit F;
#define DEFINE_ANIMALS(F) Animal F;

ZOO_BLOCK(MyZoo, FRUITS, ANIMALS);

M_FOR_EACH(DEFINE_FRUITS, FRTS),实际上我想做M_FOR_EACH(DEFINE_FRUITS, __VA_ARGS__)__VA_ARGS__ 都来自水果(即苹果、香蕉、樱桃)。如何更改我的宏来执行此操作?

【问题讨论】:

  • 如果你真的需要这个,请使用 Boost 的预处理器库。
  • 如果我们不使用 boost 库怎么办?
  • @Fake 他们在很大程度上是在重新发明轮子。

标签: c macros metaprogramming c-preprocessor variadic-macros


【解决方案1】:

我不确定这是否是您要查找的内容,但括号中的水果和动物组未解决。您可以使用 M_IDmacro 将它们“展平”,例如:

#define M_ID(...) __VA_ARGS__

#define FRUITS M_ID(apple, banana, cherry)
#define ANIMALS M_ID(dog, monkey)

#define ZOO_BLOCK(NAME, FRTS, ANMLS) struct NAME##Block {   \
  M_FOR_EACH(DEFINE_FRUITS, FRTS)                           \
  M_FOR_EACH(DEFINE_ANIMALS, ANMLS)                          \
}

#define DEFINE_FRUITS(F) Fruit F;
#define DEFINE_ANIMALS(F) Animal F;

ZOO_BLOCK(MyZoo, FRUITS, ANIMALS);

这与更正 DEFINE_ANIMAL/S 中的一个小错字一起产生:

struct MyZooBlock { 
    Fruit apple;
    Fruit banana;
    Fruit cherry;
    Animal dog;
    Animal monkey;
};

【讨论】:

  • 您可以通过使用M_ID 来解压缩ZOO_BLOCK 中的参数列表,而不是要求将其附加到输入,即M_FOR_EACH(DEFINE_FRUITS, M_ID FRTS),来稍微提高抽象。
  • @Leushenko:是的,好点子。但是使用外部的M_ID 宏,您不需要额外的宏来创建实体:ZOO_BLOCK(MyZoo, M_ID(kiwi, pear), M_ID(cat));,这可能很方便。
【解决方案2】:

如果你想根据列表生成结构,我会使用高阶宏。 这不需要您拥有另一个实际执行循环解析的宏。

#define FRUITS(V) \
    V(apple) \
    V(banana) \
    V(cherry)

#define ANIMALS(V) \
    V(dog) \
    V(monkey)

#define VISIT_ANI_STRUCT(A) \
    Animal A;

#define VISIT_FRU_STRUCT(F) \
    Fruit F;

#define ZOO_BLOCK(NAME, GEN_ANI,GEN_FRU) \
    struct NAME ## Block { \
        ANIMALS(GEN_ANI) \
        FRUITS(GEN_FRU) \
    }

ZOO_BLOCK(Zoo, VISIT_ANI_STRUCT, VISIT_FRU_STRUCT);

将导致:

struct ZooBlock { Animal dog; Animal monkey; Fruit apple; Fruit banana; Fruit cherry; };

或者如果你需要相反的方式

#define ZOO_BLOCK(NAME, A, F) \
    struct NAME ## Block { \
        A(VISIT_ANI_STRUCT) \
        F(VISIT_FRU_STRUCT) \
    }

ZOO_BLOCK(Zoo, VISIT_ANI_STRUCT, VISIT_FRU_STRUCT);

【讨论】:

    猜你喜欢
    • 2011-09-11
    • 1970-01-01
    • 1970-01-01
    • 2018-01-13
    • 1970-01-01
    • 1970-01-01
    • 2013-05-21
    • 2011-08-18
    • 1970-01-01
    相关资源
    最近更新 更多