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

How do I expand a macro containing commas inside a BOOST_PP_IF

本文关键字:包含逗 IF 何展开 BOOST PP      更新时间:2023-10-16

我早些时候问了以下问题,但解决方案似乎在这种特殊情况下不起作用。

如何使用Boost预处理器多次打印逗号

我正在尝试有条件地展开包含逗号的宏。下面是一个说明问题的例子:

#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

何时应扩展到

0,0,1,2,3,3

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

#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())()

查看它的工作

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

除此之外,我将z更改为n,将TIBRA_EATEN_COMMA()更改为EATEN_COMMA。由于有些部分是多余的,您可以在这里找到一个更简单的版本。

事实证明,您可以在没有__VA_ARGS__的情况下做到这一点。在这个简单的例子中,我在函数toString<int,int>()的模板参数中使用了一个逗号工作演示

#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";
}