【问题标题】:Conditionally iterate over some items有条件地迭代某些项目
【发布时间】:2013-09-02 07:21:40
【问题描述】:

我在我的代码中重复了很多这样的项目:

for (; i != end; ++i) {
   if(!restricted(*i))
   {
     doSomethingWithI(*i)
   }
}

有没有更好的方法来做到这一点,也许使用 std 或 boost?

另一个例子:

for (; i != end; ++i) {
   if(!restricted(*i))
   {
     Path p = _pathFactory->build(*i);
     Value v = _db->load(p);
     std::string output = _styler->style(v); 
     _output->write(output);
   }
}

【问题讨论】:

  • 你能做的任何其他事情都会把 if 推到其他地方。我说的保持简单。
  • @Neil Kirk 但这正是我想要的。我希望“如果”在一个地方而不是在我的代码中。这是因为我通常只迭代非限制项。
  • 是否可以维护两个数据结构,元素/指针指向受限制/不受限制的元素?

标签: c++ boost std c++98


【解决方案1】:

您可以编写一个仿函数并使用 for_each。

class Functor {
    ...
    void operator()(Item& i)
    {
       if(...)
       {
            ...
       }
    }
};

在您的代码中的多个位置:

std::for_each(vec.begin(), vec.end(), Functor());

operator()() 被每个元素调用。

Functor 非常灵活,可以将其模板化,也可以在构造函数中传递参数。

您还可以在标头中使用一些默认的 std 仿函数。

【讨论】:

  • 每次迭代时if中的逻辑都不一样,但迭代的内容是一样的。因此我不确定函子是否是我正在寻找的解决方案。
  • 为什么不呢?一个仿函数可以有一个状态
  • @stijn 但是“如果受限制”将在每个函子中结束。
  • 您需要定义多个函子。或者以某种方式用构造函数的参数参数化一个。在极端情况下,您可以在构造函子时将 labda 函数作为参数传递。在这种情况下,您不妨使用此处建议的不同技术。
【解决方案2】:

使用 Boost Range 适配器:

int main()
{
    const std::vector<int> v { 1,2,3,-99,4 };

    boost::copy(v | filtered([](int i) { return i > 0; }),
            std::ostream_iterator<int>(std::cout, "\n"));
}

live on Coliru

也可以使用 Boost Phoenix:

int main()
{
    const std::vector<int> v { 1,2,3,-99,4 };

    boost::for_each(v | filtered(arg1 % 2 == 0), std::cout << arg1 << "\n");
}

that live on Coliru

【讨论】:

  • 为什么不在示例中使用 OP 的功能?
  • @NeilKirk 这不是从我手指上滚出来的东西吗?第二个例子是否稍微好一点?
猜你喜欢
  • 1970-01-01
  • 2010-12-08
  • 1970-01-01
  • 2019-09-04
  • 2017-06-04
  • 1970-01-01
  • 2012-09-06
  • 1970-01-01
  • 2013-08-18
相关资源
最近更新 更多