带串联参数的 X-Macro
X-Macro with concatenation parameter
我正在使用 X-Macro 通过以下代码创建枚举
#define WIDGET_OFFSETS \
X_WIDGET_OFFSET(OFFSET_HEIGHT_WA, 1, OFFSET_HEIGHT_WB, 2, OFFSET_HEIGHT_WC, 3) \
X_WIDGET_OFFSET(OFFSET_WIDTH_WA, 1, OFFSET_WIDTH_WB, 2, OFFSET_WIDTH_WC, 3) \
X_WIDGET_OFFSET(OFFSET_LENGTH_WA, 1, OFFSET_LENGTH_WB, 2, OFFSET_LENGTH_WC, 3)
#define X_WIDGET_OFFSET(a, b, c, d, e, f) a = b,
typedef enum { WIDGET_OFFSETS } Offsets_WA_e;
#undef X_WIDGET_OFFSET
我想更概括一点,这样 X-Macro table 只有四个参数。第一个参数是 general/base 名称,然后将其与其他参数连接起来。我已经将宏定义如下,它试图完成刚刚显示的代码。
#define WIDGET_OFFSETS \
X_WIDGET_OFFSET(OFFSET_HIEGHT_, 1, 2, 3) \
X_WIDGET_OFFSET(OFFSET_WIDTH_, 1, 2, 3) \
X_WIDGET_OFFSET(OFFSET_LENGTH_, 1, 2, 3)
#define EXPAND_NAME(x,y) x##y
#define EXPAND_ENUM_TYPE(z) typedef enum { WIDGET_OFFSETS } Offsets_##z_e;
#define X_WIDGET_OFFSET(a, b, c, d) EXPAND_NAME(a,WA) = b,
EXPAND_ENUM_TYPE(WA)
#undef X_WIDGET_OFFSET
编译器向我提供以下错误消息:
error: expected identifier before ‘(’ token
所以,我的问题似乎出在 "EXPAND_NAME(a, WA) = b," 表达式上。我尝试了几种不同的方法,但 none 到目前为止都有效。最后,理想情况下,我只想指定 "WA"、"WB" 和 "WC" 一次,而不是像此处的代码那样指定两次。
我确实找到了一个类似的问题,,但如果可能的话,这不是我想做的。非常感谢任何对我做错事的洞察力。
谢谢
编辑:更正了第一个 X-Macro 定义,因为它包含 copy/paste 个错误
修复第一个代码块
您的第一个示例代码应该在宏的第三行和第四行中始终使用 WIDTH 和 LENGTH:
#define WIDGET_OFFSETS \
X_WIDGET_OFFSET(OFFSET_HEIGHT_WA, 1, OFFSET_HEIGHT_WB, 2, OFFSET_HEIGHT_WC, 3) \
X_WIDGET_OFFSET(OFFSET_WIDTH_WA, 1, OFFSET_WIDTH_WB, 2, OFFSET_WIDTH_WC, 3) \
X_WIDGET_OFFSET(OFFSET_LENGTH_WA, 1, OFFSET_LENGTH_WB, 2, OFFSET_LENGTH_WC, 3)
#define X_WIDGET_OFFSET(a, b, c, d, e, f) a = b,
typedef enum { WIDGET_OFFSETS } Offsets_WA_e;
#undef X_WIDGET_OFFSET
#undef WIDGET_OFFSETS
省略噪声行和重复的空白行,得到:
typedef enum { OFFSET_HEIGHT_WA = 1, OFFSET_WIDTH_WA = 1, OFFSET_LENGTH_WA = 1, } Offsets_WA_e;
修复第二个代码块
你的第二个例子有问题,特别是它使用 Offsets_ ## z_e
代替下面显示的 Offsets_ ## z ## _e
。通常最好不要在宏定义的末尾使用分号,让分号出现在宏调用之后。这是一个指导方针;也有很多例外。
#define WIDGET_OFFSETS \
X_WIDGET_OFFSET(OFFSET_HEIGHT, 1, 2, 3) \
X_WIDGET_OFFSET(OFFSET_WIDTH, 1, 2, 3) \
X_WIDGET_OFFSET(OFFSET_LENGTH, 1, 2, 3)
#define EXPAND_NAME(x,y) x ## _ ## y
#define EXPAND_ENUM_TYPE(z) typedef enum { WIDGET_OFFSETS } Offsets_ ## z ## _e
#define X_WIDGET_OFFSET(a, b, c, d) EXPAND_NAME(a,WA) = b,
EXPAND_ENUM_TYPE(WA);
#undef X_WIDGET_OFFSET
#define X_WIDGET_OFFSET(a, b, c, d) EXPAND_NAME(a,WB) = c,
EXPAND_ENUM_TYPE(WB);
#undef X_WIDGET_OFFSET
#define X_WIDGET_OFFSET(a, b, c, d) EXPAND_NAME(a,WC) = d,
EXPAND_ENUM_TYPE(WC);
#undef X_WIDGET_OFFSET
#undef WIDGET_OFFSETS
#undef EXPAND_ENUM
#undef EXPAND_NAME
产生了:
typedef enum { OFFSET_HEIGHT_WA = 1, OFFSET_WIDTH_WA = 1, OFFSET_LENGTH_WA = 1, } Offsets_WA_e;
typedef enum { OFFSET_HEIGHT_WB = 2, OFFSET_WIDTH_WB = 2, OFFSET_LENGTH_WB = 2, } Offsets_WB_e;
typedef enum { OFFSET_HEIGHT_WC = 3, OFFSET_WIDTH_WC = 3, OFFSET_LENGTH_WC = 3, } Offsets_WC_e;
避免重复后缀
您担心的是后缀 WA、WB 和 WC 在代码中重复出现,您不想那样重复自己。可以解决它。一种方法是将参数传递给 WIDGET_OFFSETS
宏,如下所示:
#define WIDGET_OFFSETS(sx) \
X_WIDGET_OFFSET(EXPAND_NAME(OFFSET_HEIGHT, sx), 1, 2, 3) \
X_WIDGET_OFFSET(EXPAND_NAME(OFFSET_WIDTH, sx), 1, 2, 3) \
X_WIDGET_OFFSET(EXPAND_NAME(OFFSET_LENGTH, sx), 1, 2, 3)
#define EXPAND_NAME(x,y) x ## _ ## y
#define EXPAND_ENUM_TYPE(z) typedef enum { WIDGET_OFFSETS(z) } Offsets_ ## z ## _e
#define X_WIDGET_OFFSET(a, b, c, d) a = b,
EXPAND_ENUM_TYPE(WA);
#undef X_WIDGET_OFFSET
#define X_WIDGET_OFFSET(a, b, c, d) a = c,
EXPAND_ENUM_TYPE(WB);
#undef X_WIDGET_OFFSET
#define X_WIDGET_OFFSET(a, b, c, d) a = d,
EXPAND_ENUM_TYPE(WC);
#undef X_WIDGET_OFFSET
#undef WIDGET_OFFSETS
#undef EXPAND_ENUM
#undef EXPAND_NAME
这将产生以下内容,与之前相同,但 WA、WB 和 WC 在源代码中各只出现一次。
typedef enum { OFFSET_HEIGHT_WA = 1, OFFSET_WIDTH_WA = 1, OFFSET_LENGTH_WA = 1, } Offsets_WA_e;
typedef enum { OFFSET_HEIGHT_WB = 2, OFFSET_WIDTH_WB = 2, OFFSET_LENGTH_WB = 2, } Offsets_WB_e;
typedef enum { OFFSET_HEIGHT_WC = 3, OFFSET_WIDTH_WC = 3, OFFSET_LENGTH_WC = 3, } Offsets_WC_e;
我正在使用 X-Macro 通过以下代码创建枚举
#define WIDGET_OFFSETS \
X_WIDGET_OFFSET(OFFSET_HEIGHT_WA, 1, OFFSET_HEIGHT_WB, 2, OFFSET_HEIGHT_WC, 3) \
X_WIDGET_OFFSET(OFFSET_WIDTH_WA, 1, OFFSET_WIDTH_WB, 2, OFFSET_WIDTH_WC, 3) \
X_WIDGET_OFFSET(OFFSET_LENGTH_WA, 1, OFFSET_LENGTH_WB, 2, OFFSET_LENGTH_WC, 3)
#define X_WIDGET_OFFSET(a, b, c, d, e, f) a = b,
typedef enum { WIDGET_OFFSETS } Offsets_WA_e;
#undef X_WIDGET_OFFSET
我想更概括一点,这样 X-Macro table 只有四个参数。第一个参数是 general/base 名称,然后将其与其他参数连接起来。我已经将宏定义如下,它试图完成刚刚显示的代码。
#define WIDGET_OFFSETS \
X_WIDGET_OFFSET(OFFSET_HIEGHT_, 1, 2, 3) \
X_WIDGET_OFFSET(OFFSET_WIDTH_, 1, 2, 3) \
X_WIDGET_OFFSET(OFFSET_LENGTH_, 1, 2, 3)
#define EXPAND_NAME(x,y) x##y
#define EXPAND_ENUM_TYPE(z) typedef enum { WIDGET_OFFSETS } Offsets_##z_e;
#define X_WIDGET_OFFSET(a, b, c, d) EXPAND_NAME(a,WA) = b,
EXPAND_ENUM_TYPE(WA)
#undef X_WIDGET_OFFSET
编译器向我提供以下错误消息:
error: expected identifier before ‘(’ token
所以,我的问题似乎出在 "EXPAND_NAME(a, WA) = b," 表达式上。我尝试了几种不同的方法,但 none 到目前为止都有效。最后,理想情况下,我只想指定 "WA"、"WB" 和 "WC" 一次,而不是像此处的代码那样指定两次。
我确实找到了一个类似的问题,
编辑:更正了第一个 X-Macro 定义,因为它包含 copy/paste 个错误
修复第一个代码块
您的第一个示例代码应该在宏的第三行和第四行中始终使用 WIDTH 和 LENGTH:
#define WIDGET_OFFSETS \
X_WIDGET_OFFSET(OFFSET_HEIGHT_WA, 1, OFFSET_HEIGHT_WB, 2, OFFSET_HEIGHT_WC, 3) \
X_WIDGET_OFFSET(OFFSET_WIDTH_WA, 1, OFFSET_WIDTH_WB, 2, OFFSET_WIDTH_WC, 3) \
X_WIDGET_OFFSET(OFFSET_LENGTH_WA, 1, OFFSET_LENGTH_WB, 2, OFFSET_LENGTH_WC, 3)
#define X_WIDGET_OFFSET(a, b, c, d, e, f) a = b,
typedef enum { WIDGET_OFFSETS } Offsets_WA_e;
#undef X_WIDGET_OFFSET
#undef WIDGET_OFFSETS
省略噪声行和重复的空白行,得到:
typedef enum { OFFSET_HEIGHT_WA = 1, OFFSET_WIDTH_WA = 1, OFFSET_LENGTH_WA = 1, } Offsets_WA_e;
修复第二个代码块
你的第二个例子有问题,特别是它使用 Offsets_ ## z_e
代替下面显示的 Offsets_ ## z ## _e
。通常最好不要在宏定义的末尾使用分号,让分号出现在宏调用之后。这是一个指导方针;也有很多例外。
#define WIDGET_OFFSETS \
X_WIDGET_OFFSET(OFFSET_HEIGHT, 1, 2, 3) \
X_WIDGET_OFFSET(OFFSET_WIDTH, 1, 2, 3) \
X_WIDGET_OFFSET(OFFSET_LENGTH, 1, 2, 3)
#define EXPAND_NAME(x,y) x ## _ ## y
#define EXPAND_ENUM_TYPE(z) typedef enum { WIDGET_OFFSETS } Offsets_ ## z ## _e
#define X_WIDGET_OFFSET(a, b, c, d) EXPAND_NAME(a,WA) = b,
EXPAND_ENUM_TYPE(WA);
#undef X_WIDGET_OFFSET
#define X_WIDGET_OFFSET(a, b, c, d) EXPAND_NAME(a,WB) = c,
EXPAND_ENUM_TYPE(WB);
#undef X_WIDGET_OFFSET
#define X_WIDGET_OFFSET(a, b, c, d) EXPAND_NAME(a,WC) = d,
EXPAND_ENUM_TYPE(WC);
#undef X_WIDGET_OFFSET
#undef WIDGET_OFFSETS
#undef EXPAND_ENUM
#undef EXPAND_NAME
产生了:
typedef enum { OFFSET_HEIGHT_WA = 1, OFFSET_WIDTH_WA = 1, OFFSET_LENGTH_WA = 1, } Offsets_WA_e;
typedef enum { OFFSET_HEIGHT_WB = 2, OFFSET_WIDTH_WB = 2, OFFSET_LENGTH_WB = 2, } Offsets_WB_e;
typedef enum { OFFSET_HEIGHT_WC = 3, OFFSET_WIDTH_WC = 3, OFFSET_LENGTH_WC = 3, } Offsets_WC_e;
避免重复后缀
您担心的是后缀 WA、WB 和 WC 在代码中重复出现,您不想那样重复自己。可以解决它。一种方法是将参数传递给 WIDGET_OFFSETS
宏,如下所示:
#define WIDGET_OFFSETS(sx) \
X_WIDGET_OFFSET(EXPAND_NAME(OFFSET_HEIGHT, sx), 1, 2, 3) \
X_WIDGET_OFFSET(EXPAND_NAME(OFFSET_WIDTH, sx), 1, 2, 3) \
X_WIDGET_OFFSET(EXPAND_NAME(OFFSET_LENGTH, sx), 1, 2, 3)
#define EXPAND_NAME(x,y) x ## _ ## y
#define EXPAND_ENUM_TYPE(z) typedef enum { WIDGET_OFFSETS(z) } Offsets_ ## z ## _e
#define X_WIDGET_OFFSET(a, b, c, d) a = b,
EXPAND_ENUM_TYPE(WA);
#undef X_WIDGET_OFFSET
#define X_WIDGET_OFFSET(a, b, c, d) a = c,
EXPAND_ENUM_TYPE(WB);
#undef X_WIDGET_OFFSET
#define X_WIDGET_OFFSET(a, b, c, d) a = d,
EXPAND_ENUM_TYPE(WC);
#undef X_WIDGET_OFFSET
#undef WIDGET_OFFSETS
#undef EXPAND_ENUM
#undef EXPAND_NAME
这将产生以下内容,与之前相同,但 WA、WB 和 WC 在源代码中各只出现一次。
typedef enum { OFFSET_HEIGHT_WA = 1, OFFSET_WIDTH_WA = 1, OFFSET_LENGTH_WA = 1, } Offsets_WA_e;
typedef enum { OFFSET_HEIGHT_WB = 2, OFFSET_WIDTH_WB = 2, OFFSET_LENGTH_WB = 2, } Offsets_WB_e;
typedef enum { OFFSET_HEIGHT_WC = 3, OFFSET_WIDTH_WC = 3, OFFSET_LENGTH_WC = 3, } Offsets_WC_e;