Get subsets of macro values using offset

老子叫甜甜 提交于 2019-12-10 21:05:33

问题


I have a list defined as a preprocessor value #define LIST 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. I want to write a macro that gets an index 0 or 1 and evaluates to a subset of the LIST such that for index 0 it will evaluate to 0, 2, 4, 6, 8 and for index 1 it will evaluate to 1, 3, 5, 7, 9. It is guaranteed that LIST's length is even but I don't know the content in advance (it is auto generated by the users of the library I supply). This question is a follow up on this question

#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 %d\n", MACRO(0)); // print 0 2 4 6 8
printf("%d %d %d %d %d\n", MACRO(1)); // print 1 3 5 7 9

回答1:


This should be doable with help of 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]

It works by turning LIST into a Boost.Preprocessor sequence, then iterating over it and keeping only those elements whose index modulo 2 matches the index parameter of MACRO, and finally turning the resulting sequence back into a comma-separated list.


Note that there is a limit on the maximum size of a Boost.Preprocessor tuple. In version 1.66.0 (the latest as of this writing), it's 64. If your LIST is larger, it cannot be treated as a tuple (which the code above does by using (LIST) to put a pair of parentheses around it).

If you have control over the format of LIST, you could change it do be a Boost.Preprocessor sequence directly:

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

While sequences have a size limit too, it's far larger (256 in Boost 1.66.0). The macro would then change as follows:

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

If the sequence limit is still not enough, you will have to consider a more powerful code generation technique, such as a stand-alone macro processor outside the native C++ framework.



来源:https://stackoverflow.com/questions/47868671/get-subsets-of-macro-values-using-offset

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!