如何在BOOST_PP_IF中展开包含逗号的宏

时间:2014-07-16 01:08:09

标签: c++ boost-preprocessor

我之前提出过以下问题,但解决方案在这种特殊情况下似乎不起作用。

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

2 个答案:

答案 0 :(得分:5)

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

#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更改为n,将TIBRA_EATEN_COMMA()更改为EATEN_COMMA。由于某些部分是多余的,您可以找到更简单的版本here

答案 1 :(得分:0)

事实证明,您可以在没有__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";
}