使用偏移

时间:2017-12-18 12:36:46

标签: c++ c++11 macros c-preprocessor

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

的跟进
LIST

1 个答案:

答案 0 :(得分:2)

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)) \
    ) \
  )

[Live example]

通过将LIST转换为Boost.Preprocessor 序列,然后对其进行迭代并仅保留其索引模2匹配index MACRO参数的元素。 1}},最后将结果序列转换为以逗号分隔的列表。

请注意,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 ++框架之外的独立宏处理器。