BOOST_PP_SEQ_ELEM嵌套宏中的BOOST_PP_SEQ_ADD?
BOOST_PP_SEQ_ELEM with BOOST_PP_SEQ_ADD in nested macro?
我相信你可以使用BOOST_PP_SEQ_ELEM(BOOST_PP_ADD(n,1),sequence)
,但我似乎不能完全确定为什么下面的EXTRACT
宏无法编译"提供的参数太少,无法像宏一样工作"。
#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;
}
这个例子远非我想用这个做的,但现在我只是想弄清楚如何获得实际的int
和z
或float
和y
。
如果重要,实际目标是实例化模板。 我有一系列模板类,但无法弄清楚如何实例化
// vvvvvvvvvvvv
template <class X> void foo(SomeThing<X> varName);
所以这里的标志让我知道SomeThing
是否需要<X>
。 也许有更简单的方法可以解决这个问题? 我已经在模板中类的BOOST_PP_SEQ_FOR_EACH
内,所以我唯一能弄清楚该怎么做的就是传递这个丑陋的参数序列。 FWIW 我知道int<X>
无效,这只是测试......
诊断提示
通常,预处理器宏比"小程序"更容易使用预处理器进行调试。 例如,您在此处拥有的内容需要完整的编译和启动才能看到问题;但是如果你注释掉#include <iostream>
和#include <boost/preprocessor/stringize.hpp>
,并将整个主函数替换为ALL_ARGS(MY_SEQUENCE)
,那么你可以简单地启动你的预处理器并直接查看它的输出;无需编译/运行。
这不仅更快,而且你可以在代币级别上玩,生产可以帮助你的东西,而不必担心生产可以编译的东西。
跟踪问题
使用上面的转换,我通过将参数EXTRACT
更改为EXTRACT_
来执行ALL_ARGS
的单个扩展(在重现问题之后)。 这迭代得很好。 接下来,我将ALL_ARGS
更改为扩展的输出,将每个EXTRACT_
分解为单独的行并添加人工标签,然后将EXTRACT_
改回EXTRACT
;例如:
0_ EXTRACT(2, 0, (1)(int)(z)(0)(float)(y))
1_ EXTRACT(2, 1, (1)(int)(z)(0)(float)(y))
...
再次通过预处理器运行它表明所有扩展都很好,除了第六个:
5_ EXTRACT(2, 5, (1)(int)(z)(0)(float)(y))
考虑到这一点,很容易发现。 问题确实出在这一部分:
BOOST_PP_SEQ_ELEM(BOOST_PP_ADD(n,1),args)
。当EXTRACT
在 n=5 的情况下运行时,这相当于BOOST_PP_SEQ_ELEM(6, (1)(int)(z)(0)(float)(y))
。 这里没有元素偏移量 6,因此宏崩溃了。 请注意,BOOST_PP_NOT(BOOST_PP_MOD(5,3))
是0
,因此外部BOOST_PP_IIF
不会选择内部,但它仍然必须对其进行评估。
替代方法
也许有更简单的方法可以解决这个问题?
绝对。 使用不同的数据结构。 在这里,您的策略是使用大小为 3*n 的序列来表示某个 n,然后在序列中每 3 个项目中挑选出。
通过一些摆弄,您当然可以做到这一点,但是您需要这样做的全部原因是因为您实际上没有一系列物品......相反,您有一系列3 个项目的集合。 如果您将数据结构更改为 3 元组序列,这将变得容易得多;您只需要一个IIF
、一个FOR_EACH
和几个工作宏:
#include <boost/preprocessor/control/iif.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#define MY_SEQUENCE ((1,int,z))((0,float,y))
#define APPLY_EXTRACT(r,data,elem) EXTRACT elem
#define EXTRACT(FLAG_,TYPE_,PNAME_) BOOST_PP_IIF(FLAG_, TYPE_, "narp")
#define ALL_ARGS(args) BOOST_PP_SEQ_FOR_EACH(APPLY_EXTRACT, _, MY_SEQUENCE)
ALL_ARGS(MY_SEQUENCE)
在堆叠歪歪上看到这个
- 理解boost::asio-async_read在无需读取内容时的行为
- boost::进程间消息队列引发错误
- 如何运行位于boost/libs/python/example/tutorial目录中的hello.cpp和Jamfil
- cmake如何在fedora工作站中找到boost静态库包
- CMake项目Boost库错误:Boost/config/compiler/gcc.hpp:165:10:致命错误:cs
- Boost Graph Library,修复节点大小
- 什么是"#include <boost/functional/hash.hpp> "?
- 基于boost的程序的静态链接——zlib问题
- C++:如何在CLion IDE中安装Boost
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 如何在boost beast http请求中设置http头
- Boost Spirit,获取迭代器内部语义动作
- boost::asio::steady_timer()与sleep()我应该使用哪一个
- boost::asio如何生成多个协同程序,然后加入它们
- 当我尝试使用 sstream 和分面将 Boost Time_duration转换为字符串时,我没有得到所需的格式
- Visual Studio(或任何其他工具)能否将地址解释为调用堆栈(boost上下文)的开头
- 如何使用boost::具有嵌套结构和最小代码更改的序列化
- 使用Boost Interprocess创建托管共享内存需要很长时间
- Boost::posix_time::ptime舍入到给定的分钟数
- boost xml parsingl将xml的路径作为变量发送