3

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);
   }
}
Baz
  • 12,713
  • 38
  • 145
  • 268
  • 1
    Anything else you can do will just shove the if somewhere else. Keep it simple I say. – Neil Kirk Sep 02 '13 at 07:33
  • @Neil Kirk But this is exactly what I want. I want that "if" in one place instead of all over my code. This is because I generally only iterate over non-restricted items. – Baz Sep 02 '13 at 07:46
  • Is it possible to maintain two data structures, with elements/pointers to restricted/unrestricted elements? – Neil Kirk Sep 02 '13 at 07:50

2 Answers2

2

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.

Patrik Beck
  • 2,455
  • 1
  • 19
  • 24
  • The logic within the if is different each time I iterate, but what is being iterated over is the same. Therefore I'm not sure if a functor is the solution I'm looking for. – Baz Sep 02 '13 at 07:43
  • why not? a functor can have a state – stijn Sep 02 '13 at 07:48
  • @stijn But the "if restricted" will end up in each functor. – Baz Sep 02 '13 at 07:57
  • You would need to have multiple functors defined. Or somehow parametrize one with an argument to the constructor. In an extreme case you could pass labda function as a parameter when constructing the functor. In which case you might as well use a different technique suggested here. – Patrik Beck Sep 02 '13 at 08:11
2

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

sehe
  • 374,641
  • 47
  • 450
  • 633