使用偏移量获取宏值的子集

Get subsets of macro values using offset

本文关键字:子集 获取 偏移量      更新时间:2023-10-16

>我有一个定义为预处理器值的列表#define LIST 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.我想编写一个宏,该宏获取索引 0 或 1 并计算LIST的子集,以便对于索引 0,它将计算为0, 2, 4, 6, 8,对于索引 1,它将计算为1, 3, 5, 7, 9。保证LIST的长度是均匀的,但我事先不知道内容(它是由我提供的库的用户自动生成的)。这个问题是这个问题的后续

#define LIST 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
#define MACRO(index) 
use LIST and index
// For LIST that given in the example
printf("%d %d %d %d %dn", MACRO(0)); // print 0 2 4 6 8
printf("%d %d %d %d %dn", MACRO(1)); // print 1 3 5 7 9

这应该在 Boost.Preprocessor 的帮助下是可行的:

#define OUTPUT_CORRECT_OFFSET(r, offset, idx, elem) 
BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(BOOST_PP_MOD(idx, 2), offset), (elem))
#define MACRO(index) 
BOOST_PP_SEQ_ENUM( 
BOOST_PP_SEQ_FOR_EACH_I( 
OUTPUT_CORRECT_OFFSET, 
index, 
BOOST_PP_TUPLE_TO_SEQ((LIST)) 
) 
)

[现场示例]

它的工作原理是将LIST转换为 Boost.Preprocessor 序列,然后迭代它并仅保留索引模 2 与MACROindex参数匹配的元素,最后将生成的序列转换回逗号分隔的列表。


请注意,对 Boost.Preprocessor 元组的最大大小有限制。在版本 1.66.0(撰写本文时的最新版本)中,它是 64。如果您的LIST较大,则不能将其视为元组(上面的代码通过使用(LIST)在其周围放置一对括号来实现元组)。

如果你可以控制LIST的格式,你可以直接将其更改为 Boost.Preprocessor 序列:

#define LIST (0)(1)(2)(3)(4)(5)(6)(7)(8)(9)

虽然序列也有大小限制,但它要大得多(在 Boost 1.66.0 中为 256)。然后,宏将更改如下:

#define MACRO(index) 
BOOST_PP_SEQ_ENUM( 
BOOST_PP_SEQ_FOR_EACH_I( 
OUTPUT_CORRECT_OFFSET, 
index, 
LIST 
) 
)

如果序列限制仍然不够,则必须考虑更强大的代码生成技术,例如本机C++框架之外的独立宏处理器。