首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于Boost foreach的enumerate_foreach实现

基于Boost foreach的enumerate_foreach实现
EN

Stack Overflow用户
提问于 2012-07-31 04:59:04
回答 1查看 838关注 0票数 3

为了说明这个问题:我已经在一个更大的工具箱中实现了各种C++实用程序函数和宏,供我自己使用。最近,我制作了各种基于BOOST_FOREACH的循环宏,以及可迭代的意识函数。

长话短说,我在制作一个enumerate-loop时遇到了困难,它使用了BOOST_FOREACH,但是传递了一个额外的参数,这个参数在循环的每一次迭代中都会增加。这将与Python中的枚举命令非常相似,我发现它在不添加大量锅炉板代码的情况下遍历任意迭代器时非常有用。宏采用类似于BOOST_FOREACH的形式:

代码语言:javascript
复制
ENUMERATE_FOREACH(COUNT, VAR, COL)

并且可以有效地做到这一点,但不依赖于放置不平衡的“}”来关闭(或其他循环结束宏):

代码语言:javascript
复制
COUNT = 0; BOOST_FOREACH(VAR, COL) { COUNT++; ...Rest of loop...

现在,在我被指控试图在C++中生成一个非C++操作符之前,我完全意识到这是在将一个外来的概念塞进C++中,而不是尝试PythonizedC++代码。我只是好奇是否完全有可能用已知的工具集/boost来实现这样的循环,而没有极端的依赖关系。拥有这样的宏定义将消除某些循环样式的可能的bug源,在这里,我需要在迭代时计数,并且它消除了count变量的用途。

我曾想过在COL变量进入BOOST_FOREACH之前对它做一个模板包装器,但是COL的很多可能性使得在没有不同版本的ENUMERATE_FOREACH和重新实现大量BOOST_FOREACH的情况下,使用一些可迭代变量的组合是困难的/不可能的--这是一个令人畏惧和愚蠢的任务,没有大量的测试/时间。

执行单独的内联函数可以工作,但是循环的语法就会中断,而我将更多地理解每种类型的运算符函数传递情况(我已经实现了)。

这使我不得不从boost的库中获取foreach.hpp的最后一行,并在附加参数上插入自己的增量运算符。然后,我变得依赖于boost版本,并担心新的更新(任何语法更改),以促进打破我的讨厌的自定义宏。

我考虑的最后一个选项是执行ENUMERATE_BEGIN和ENUMERATE_END来隐藏迭代器增量操作。这种方法比单个宏更容易出错,因为用户必须放置两个宏而不是一个宏--尽管这可能是唯一的简单解决方案。

我试着环顾一下SO和其他消息来源,看看以前是否有人尝试过这一点,但运气不佳。希望有人已经成功地使用了这样的实现概念,或者有了改变我的方法的想法。如果没有一种干净的方法来做这件事,那么当我想计数的时候,我可以继续用一个count++启动循环。再一次,这是一种好奇心,有人可能会提出,我所争论的其中一个想法是一种完全合理的方法,或者说它会得到最好的结果。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-07-31 21:13:31

在阅读了Joachim的响应之后,我基本上很满意,但我试图操作BOOST_FOREACH,直到我能够至少以一种非常讨厌的方式来操作为止,然后我发现我实际上可以以一种温和的方式实现计数器,而无需重写整个宏或在BOOST_FOREACH_NEXT上执行一些#undef #define语句。

我滥用BOOST_FOREACH有一个(VAR =derefence(.);.)的事实。语句,并在VAR和=之间放置一个结构,使我得到(VAR = IncrementCountAndPassRHS =derefence(.);.)。

我还没有对宏扩展问题进行过多的测试,但我认为在for循环中它是安全的。

编辑添加了更新,以修复同一行中多个循环的变量范围名称重叠问题。

代码语言:javascript
复制
namespace loopnamespace {
template<typename T>
void incrementT(T *t) {
    (*t)++;
}

struct IncrementCounterPassthrough {
    bool checker;
    boost::function<void(void)> incrementer;

    template<typename Count>
    IncrementCounterPassthrough(Count& t) {
        t = -1;
        checker = true;
        incrementer = boost::bind(&incrementT<Count>, &t);
    }

    template<typename T>
    T& operator=(T& rhs) {
        incrementer();
        return rhs;
    }
};
}

#define ENUMERATE_FOREACH(COUNT, VAR, COL)                                                                   \
    for(::loopnamespace::IncrementCounterPassthrough BOOST_FOREACH_ID(_foreach_count_pass)(COUNT);           \
        BOOST_FOREACH_ID(_foreach_count_pass).checker; BOOST_FOREACH_ID(_foreach_count_pass).checker = false)\
    BOOST_FOREACH(VAR = BOOST_FOREACH_ID(_foreach_count_pass), COL)

允许我做:

代码语言:javascript
复制
std::string hello( "Hello, boost world!" );
unsigned int value;
ENUMERATE_FOREACH( value, char ch, hello ) {
   std::cout << ch << " => " << value << "\n";
}

到产出:

代码语言:javascript
复制
H => 0
e => 1
l => 2
l => 3
o => 4
, => 5
  => 6
b => 7
o => 8
o => 9
s => 10
t => 11
  => 12
w => 13
o => 14
r => 15
l => 16
d => 17
! => 18
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11733364

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档