宏可以替换出现在其参数列表中的标记吗?

时间:2017-11-29 04:33:57

标签: c c-preprocessor

我正在尝试在其自身中插入一系列字节的大小。如果我想将大小作为前缀,那么这可行:

#define COUNT(...) sizeof((uint8_t[]){__VA_ARGS__})
#define PREPEND_COUNT(...) COUNT(__VA_ARGS__), __VA_ARGS__
uint8_t x[] = {PREPEND_COUNT(10, 20, 30, 40)};
//        x = {4, 10, 20, 30, 40}

但是,我还希望能够在扩展中的其他位置插入大小。阅读this page提供了一系列可以实现的工具。

是否可以按照以下方式创建内容?

uint8_t x[] = {ADD_COUNT(10, 20, THE_COUNT, 30, 40)};
//        x = {10, 20, 4, 30, 40}

这是我的天真和不成功的方法:

#define ADD_COUNT2(THE_COUNT, ...) __VA_ARGS__
#define ADD_COUNT(...) ADD_COUNT2(COUNT(__VA_ARGS__), OBSTRUCT(__VA_ARGS__)))

1 个答案:

答案 0 :(得分:1)

此方法使用boost预处理器。你的规范中有一些含糊之处;为简单起见,我将假设THE_COUNT应该简单地替换为列表的大小减一。

#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/arithmetic/dec.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/tuple/eat.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/tuple/size.hpp>

#define SECOND(...) SECOND_I(__VA_ARGS__,,)
#define SECOND_I(F,S,...) S

#define THE_COUNT_MATCHES_THE_COUNT ,PRED_OF_COUNT
#define PRED_OF_COUNT(...) BOOST_PP_DEC(BOOST_PP_TUPLE_SIZE((__VA_ARGS__)))

#define ELEM_OR_COUNT(z,n,data) \
    SECOND(BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(n,data),_MATCHES_THE_COUNT), \
           BOOST_PP_TUPLE_ELEM(n,data) BOOST_PP_TUPLE_EAT())data

#define ADD_COUNT(...) BOOST_PP_ENUM(BOOST_PP_TUPLE_SIZE((__VA_ARGS__)),ELEM_OR_COUNT,(__VA_ARGS__))

这需要一些解释。

SECOND宏使用与检测部分中的网站CHECK宏类似的技术。我使用它来提供可以被覆盖的默认值;为此,我构建了一个“匹配器”标记作为第一个参数。对于我想要不同扩展的东西,我定义了一个匹配的宏(类似于该部分中的PROBE),它通过包含逗号来注入第二个参数。

在这种情况下,我希望THE_COUNT扩展为PRED_OF_COUNT,因此我构建了一个匹配令牌THE_COUNT_MATCHES_THE_COUNT(我打算从THE_COUNT_MATCHES_加上每个参数构建)要做到这一点。数据在争论之后,因此PRED_OF_COUNT有正确的数字。对于默认情况(一个数字)我只是把那个数字;因为我之后推了数据,但是不想看到它,我添加了一个吃宏(这有点奇怪; BOOST_PP_TUPLE_EAT()扩展为一个宏吃了一个元组;这不是宏本身。)

ELEM_OR_COUNTBOOST_PP_ENUM正文宏;看到那份文件。

ADD_COUNT推动了这一机制。

最后,here's your coliru.stacked-crooked.com demo