【问题标题】:How do I expand a macro containing commas inside a BOOST_PP_IF如何在 BOOST_PP_IF 中展开包含逗号的宏
【发布时间】:2014-09-06 09:08:59
【问题描述】:

我之前问过以下问题,但该解决方案似乎不适用于这种特殊情况。

How do I print out a comma multiple times using Boost Preprocessor

我正在尝试有条件地扩展包含逗号的宏。这是一个说明问题的示例:

#define TEST(...)\
    BOOST_PP_REPEAT( \
        BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \
        MACRO, \
        BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__))

#define MACRO(z, n, data) BOOST_PP_IF(1,MACRO_CONTAINING_COMMA(z, z),MACRO_CONTAINING_COMMA(z, z))

#define MACRO_CONTAINING_COMMA(_NAME, _NAME2) _NAME TIBRA_EATEN_COMMA() _NAME2

#define EATEN_COMMA BOOST_PP_IF(1,BOOST_PP_COMMA,BOOST_PP_TUPLE_EAT())
TEST(1,2,3,4)

这扩展为

BOOST_PP_IIF BOOST_PP_IIF BOOST_PP_IIF BOOST_PP_IIF

什么时候应该展开

0,0 1,1 2,2 3,3

【问题讨论】:

  • BOOST_PP_COMMA_IF 有帮助吗?
  • @chris,这是一个简化的例子,在我的实际代码中CODE_CONTAINING_COMMA 是自定义的class 声明,所以我认为BOOST_PP_COMMA_IF 不会有太大帮助。跨度>
  • 嗯,有一种技术也可能有所帮助:coliru.stacked-crooked.com/a/b75fdccefcec6b7c
  • 嗯,这对我来说扩展得很好,因为逗号括在括号中。
  • @chris 这个链接看起来很有趣,我认为这是一个很好的解决方案!

标签: c++ boost-preprocessor


【解决方案1】:

您可以通过先选择宏然后调用它来延迟调用宏:

#define TEST(...)\
    BOOST_PP_REPEAT( \
        BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \
        MACRO, \
        BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__))

#define MACRO(z, n, data) BOOST_PP_IF(1,MACRO_CONTAINING_COMMA,MACRO_CONTAINING_COMMA)(n, n)

#define MACRO_CONTAINING_COMMA(_NAME, _NAME2) _NAME EATEN_COMMA _NAME2

#define EATEN_COMMA BOOST_PP_IF(1,BOOST_PP_COMMA,BOOST_PP_TUPLE_EAT())()

See it work

IF 调用扩展为没有调用的宏或在调用时丢弃参数的东西。选择一个后,最后的括号会使用所需的参数调用它,而不会妨碍逗号。

除此之外,我将z 更改为nTIBRA_EATEN_COMMA() 更改为EATEN_COMMA。由于有些部分是多余的,你可以找到一个更简单的版本here

【讨论】:

  • 您的新示例使用MACRO 末尾的一对括号并使用#define MACRO_CONTAINING_COMMA()。随着事情变得更加嵌套,我相信您最终需要将这两个东西放在那里,并且任何嵌套的东西都选择要调用的宏。实际上,它也适用于删除 EATEN_COMMA() 中的括号并在第一个 IF() 之后添加一些括号。
  • @Jason,您可以在IF 中调用它,并带有选择宏所需的参数。
  • @Jason,(...) 后面不应该有括号。如果您使用参数调用它,还要确保 EATEN_COMMA 是一个类似函数的宏。
  • @Jason,选择一个在第一个 IF 中扩展为 abc, def 的宏,以便它在 IF 上使用尾随 () 扩展。
  • @Jason,首先,您需要 n 进行循环迭代。不管怎样,在这个例子中,你可以做同样的事情,把参数移到IF之外:coliru.stacked-crooked.com/a/635e9fd105c89f33。您还可以将其与在 IF 中调用 MACRO_CONTAINING_COMMA 结合起来,将其扩展为带有两个参数的宏。请注意,我的示例还将 TIBEATEN_COMMA() 更改为 EATEN_COMMA
【解决方案2】:

事实证明,没有__VA_ARGS__ 也可以做到这一点。在这个简单的例子中,我在函数 toString<int,int>() Working demo 的模板参数中使用了一个逗号:

#include <boost/lexical_cast.hpp>
#include <boost/preprocessor.hpp>
#include <iostream>
#include <string>

#define SEQUENCE (1)(2)(3)(4)(5)(6)(7)(8)(9)(10)

#define IGNORE_ARG(arg)
#define GET_NAME(data) BOOST_PP_SEQ_ELEM(0, data)
#define GET_BELOW(data) BOOST_PP_SEQ_ELEM(1, data)

#define PARSE_SEQUENCE(r, data, elem)                  \
    BOOST_PP_IF(                                       \
        BOOST_PP_GREATER_EQUAL(elem, GET_BELOW(data)), \
            GET_NAME(data), IGNORE_ARG)                \
    (elem)

#define SKIP_NUMBERS_BELOW(name, below)                \
    BOOST_PP_SEQ_FOR_EACH(PARSE_SEQUENCE, (name)(below), SEQUENCE)

#define TEST(name) SKIP_NUMBERS_BELOW(name, 4)

#define MACRO_CONTAINING_COMMA(N) toString<N, 2 * N>() <<

template <int a, int b> // whatever, I just need a comma here.
std::string toString() {
    return boost::lexical_cast<std::string>(a) + ":" + boost::lexical_cast<std::string>(b) + " ";
}

int main() {
    std::cout << TEST(MACRO_CONTAINING_COMMA) "\n";
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-14
    • 2010-10-23
    • 1970-01-01
    • 2021-05-16
    • 2011-12-25
    • 2016-12-14
    • 1970-01-01
    • 2018-12-11
    相关资源
    最近更新 更多