BOOST_PP_SEQ_ELEM与嵌套宏中的BOOST_PP_SEQ_ADD?

时间:2017-09-25 14:08:45

标签: c++ boost macros

我确信您可以使用BOOST_PP_SEQ_ELEM(BOOST_PP_ADD(n,1),sequence),但我似乎无法确定以下EXTRACT宏无法使用&#34进行编译的原因提供的参数像macro"。

#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/control/iif.hpp>
#include <boost/preprocessor/arithmetic/mod.hpp>
#include <boost/preprocessor/logical/not.hpp>
#include <boost/preprocessor/arithmetic/add.hpp>

#include <iostream>

// attempt 2.7 beta
#define EXTRACT(z, n, args) \
    BOOST_PP_IIF(\
        /* on every third index */ \
        BOOST_PP_NOT(BOOST_PP_MOD(n,3)),\
        /* check the flag */ \
        BOOST_PP_IIF(BOOST_PP_SEQ_ELEM(n,args),\
            /*BOOST_PP_SEQ_ELEM(n,args),*/ \
            BOOST_PP_SEQ_ELEM(BOOST_PP_ADD(n,1),args),\
            "narp"\
        ),\
    )

// absurd wrapper for extract
#define ALL_ARGS(args) BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(args),EXTRACT,args)

// every third element is a "flag"
//                   v          v
#define MY_SEQUENCE (1)(int)(z)(0)(float)(y)

int main(int argc, const char **argv) {
    std::cout <<
        BOOST_PP_STRINGIZE(ALL_ARGS(MY_SEQUENCE))
        << std::endl;
}

这个例子远非我想要做的事情,但是现在我只想弄清楚如何获得实际的intz或{{1} }和float

如果重要,实际目标是实例化模板。我有一系列模板类,但我无法弄清楚如何实例化

y

所以这里的标志让我知道// vvvvvvvvvvvv template <class X> void foo(SomeThing<X> varName); 是否需要SomeThing。也许有一种更简单的方法来解决这个问题?我已经在模板中的类<X>内了,所以我唯一能弄清楚如何做的就是传递这个丑陋的参数序列。 FWIW我知道BOOST_PP_SEQ_FOR_EACH不是有效的,这只是测试......

1 个答案:

答案 0 :(得分:2)

诊断提示

一般情况下,预处理器宏使用预处理器比使用预处理器更容易调试&#34;微小程序&#34;。例如,您在此处需要完整的编译和启动以查看问题;但是如果你注释掉#include <iostream>#include <boost/preprocessor/stringize.hpp>,并用ALL_ARGS(MY_SEQUENCE)替换整个主函数,那么你可以直接启动预处理器并查看其输出;无需编译/运行。

这不仅速度更快,而且您可以在令牌级别上进行游戏,以制作可以帮助您的内容,而不必担心会产生可编译的内容。

追踪问题

使用上面的转换,我通过将参数ALL_ARGS更改为EXTRACT,对EXTRACT_进行了单次扩展(在重现问题之后)。 This iterated just fine。接下来,我将ALL_ARGS更改为扩展的输出,在单独的行中分解每个EXTRACT_并添加人工标签,然后将EXTRACT_更改回EXTRACT; e.g:

0_  EXTRACT(2, 0, (1)(int)(z)(0)(float)(y))
1_  EXTRACT(2, 1, (1)(int)(z)(0)(float)(y))
...

再次通过预处理器运行,显示所有扩展都很好,except for the sixth one

5_  EXTRACT(2, 5, (1)(int)(z)(0)(float)(y))

考虑到这一点很容易发现。问题确实存在于这一部分:

BOOST_PP_SEQ_ELEM(BOOST_PP_ADD(n,1),args)

...当{= 1}}以n = 5运行时,这相当于EXTRACT。这里没有元素偏移6,因此宏崩溃。请注意,BOOST_PP_SEQ_ELEM(6, (1)(int)(z)(0)(float)(y))BOOST_PP_NOT(BOOST_PP_MOD(5,3)),因此外部0不会选择内部,但它仍然必须评估 it。

替代方法

也许有更简单的方法来解决这个问题?

绝对。使用不同的数据结构。在这里,你的策略是对一些n使用大小为3 * n的序列,然后在序列中挑选出每3个项目。

通过一些摆弄你肯定可以做到这一点,但你需要的全部原因是因为你没有真正拥有一系列项目 ......而是你有一系列的 3件套。如果将数据结构更改为3元组序列,则更多更容易;您只需要一个BOOST_PP_IIF,一个IIF和一些工作宏:

FOR_EACH

See this on stacked-crooked