Conditionally iterate over some items

836 Views Asked by At

I'm iterating some items like this quite a lot in my code:

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

Is there a nicer way of doing this, perhaps with std or boost?

Another example:

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);
   }
}
2

There are 2 best solutions below

4
On

You can write a functor and use for_each.

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

In your code, at multiple places:

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

operator()() gets called on every element.

Functors are very flexible, you can templetize it, or you can pass parameters to it in the constructor.

There are also some default std functors you can use in the header.

2
On

Using Boost Range adaptors:

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

See it live on Coliru

Using a touch of Boost Phoenix as well:

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

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

See that live on Coliru