【问题标题】:A Macro for Building a Linked List用于构建链表的宏
【发布时间】:2016-02-14 06:36:41
【问题描述】:

我正在以编程方式生成 C++ 代码。我经常需要输出以下形式的链表,

PTR(new List(a,PTR(new List(NULL,NULL))))
PTR(new List(a, PTR(new List(b,PTR(new List(NULL,NULL))))))

随着列表大小的增长,生成的代码变得越来越难看,我想知道是否可以定义表单的可变参数宏,

LIST(a)
LIST(a,b)

这将扩展为第一种形式的代码。

【问题讨论】:

  • 是的,Boost.Preprocessor 是一个很好的开始。
  • @chris,你能指出我如何做到这一点的文章吗?对于嵌入式平台,我宁愿不依赖于单个宏的 boost。
  • 您当然可以使用 Boost.PP 而无需 Boost 的其余部分。而且都是宏,所以除了你生成的,没有代码。
  • 使用宏会适得其反。使用这些宏绝对不聪明。只需不使用宏即可避免您遇到的问题。使用链表通常也会适得其反。然而,在少数情况下,它们是有保证的。它们代表什么?

标签: c++ g++ c-preprocessor


【解决方案1】:

这里是 one way 使用 Boost.Preprocessor,它不依赖于 Boost 的任何其他部分:

#include <boost/preprocessor.hpp>

#define FOR_EACH_OP(r, data, elem) PTR(new List(elem,
#define DOUBLE_RPAREN(...) ))

#define LIST(...) LIST_I(BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
#define LIST_I(seq) \
    BOOST_PP_SEQ_FOR_EACH(FOR_EACH_OP, /*empty*/, seq) \
    PTR(new List(NULL,NULL)) \
    BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(seq), DOUBLE_RPAREN, /*empty*/)

LIST(a) // PTR(new List(a, PTR(new List(NULL,NULL)) ))
LIST(a,b) // PTR(new List(a, PTR(new List(b, PTR(new List(NULL,NULL)) )) ))

LIST 只是将参数转换为“PP 序列”,这提供了方便的FOR_EACH。对于每个参数,左侧部分是建立起来的。然后添加NULL 部分。最后,根据给出的参数数量添加匹配的右括号。

免责声明:LIST() 将无法按预期工作,因为它是带有一个(空)参数的调用。


如果你真的对 Boost 过敏,可以make simplified versions of these。例如,一种最多支持四个参数的方法:

#define CAT(_0, _1) CAT_I(_0, _1)
#define CAT_I(_0, _1) _0##_1

#define ARG5(_0, _1, _2, _3, _4, ...) _4
#define NARGS(...) ARG5(__VA_ARGS__, 4, 3, 2, 1,)
#define OVERLOAD(prefix, ...) CAT(prefix, NARGS(__VA_ARGS__))

#define ELEM(i, ...) CAT(ELEM_, i)(__VA_ARGS__,)
#define ELEM_0(_0, ...) _0
#define ELEM_1(_0, _1, ...) _1
#define ELEM_2(_0, _1, _2, ...) _2
#define ELEM_3(_0, _1, _2, _3, ...) _3

#define FOR_EACH(macro, ...) OVERLOAD(FOR_EACH_, __VA_ARGS__)(macro, __VA_ARGS__)
#define FOR_EACH_1(macro, ...) macro(ELEM(0, __VA_ARGS__))
#define FOR_EACH_2(macro, ...) FOR_EACH_1(macro, __VA_ARGS__) macro(ELEM(1, __VA_ARGS__))
#define FOR_EACH_3(macro, ...) FOR_EACH_2(macro, __VA_ARGS__) macro(ELEM(2, __VA_ARGS__))
#define FOR_EACH_4(macro, ...) FOR_EACH_3(macro, __VA_ARGS__) macro(ELEM(3, __VA_ARGS__))

#define REPEAT(n, macro) CAT(REPEAT_, n)(macro)
#define REPEAT_1(macro) macro()
#define REPEAT_2(macro) REPEAT_1(macro) macro()
#define REPEAT_3(macro) REPEAT_2(macro) macro()
#define REPEAT_4(macro) REPEAT_3(macro) macro()

#define FOR_EACH_MACRO(elem) PTR(new List(elem,
#define DOUBLE_RPAREN() ))

#define LIST(...) LIST_I(NARGS(__VA_ARGS__), __VA_ARGS__)
#define LIST_I(n, ...) \
    FOR_EACH(FOR_EACH_MACRO, __VA_ARGS__) \
    PTR(new List(NULL,NULL)) \
    REPEAT(n, DOUBLE_RPAREN)

LIST(a) // PTR(new List(a, PTR(new List(NULL,NULL)) ))
LIST(a,b) // PTR(new List(a, PTR(new List(b, PTR(new List(NULL,NULL)) )) ))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-05
    • 2011-06-06
    • 2020-08-26
    • 1970-01-01
    • 2021-01-04
    • 2012-08-13
    • 1970-01-01
    相关资源
    最近更新 更多