我目前的解决方案:
#define TEMPLATE_X_YX_(X, Y, a, b, c) a ## X ## b ## Y ## X ## c
// other templates may also exist, with different parameter arrangements
#define GENERATOR(name, template, ...) \
const auto name##1 = &TEMPLATE##template(A, 1, __VA_ARGS__); \
const auto name##2 = &TEMPLATE##template(B, 2, __VA_ARGS__); \
const auto name##3 = &TEMPLATE##template(C, 3, __VA_ARGS__);
GENERATOR(example, _X_YX_, example_, _mid_, _suffix)
// expected output:
const auto example1 = &example_A_mid_1A_suffix;
const auto example2 = &example_B_mid_2B_suffix;
const auto example3 = &example_C_mid_3C_suffix;
但是我发现令人沮丧的是需要定义和引用TEMPLATE
宏,并且它与我使用的实际模板定义不一致。我喜欢的可能是:
GENERATOR(example, example_, X, _mid_, Y, X, _suffix)
我尝试了一些嵌套实验,并试图强制将X和Y扩展为更深层次的宏的参数,但预处理器没有这样做。
这方面的一个应用是快速地将具有复杂名称的每个类型的C函数的大列表折叠成C++重载的简单名称。
我想知道我是否可以为替换参数做一些预定义的宏(可能在它们的定义中包含逗号),以在下降之前强制执行一轮额外的宏扩展,但我现在无法想出一个明确的计划。即使成功了,也可能是非法的。
2条答案
按热度按时间guz6ccqo1#
这是可能的,但是编写在循环体内部使用外部状态的宏循环(在你的例子中,状态是
X
和Y
的值)是很棘手的,所以我将使用一个小库:macro_sequence_for
(我是作者)。我还对模式语法做了一点修改,因为循环
(a)(b)(b)
(与a, b, c
相反)形式的序列更容易。在逗号分隔的列表上循环需要样板宏,其数量限制了序列元素的最大数量。在www.example.com上运行gcc.godbolt.org
宏实现:
这里有两个循环,第一个循环的输出作为第二个循环的输入序列。
第一个循环扩展输入中的变量,因此
(x_is_)(X)(_and_y_is_)(Y)
变成(x_is_)(A)(_and_y_is_)(B)
,第二个循环将元素连接成一个标识符。tktrz96b2#
这似乎是有效的,直到一个适度的限制: