Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ STL - iterate through everything in a sequence

Tags:

c++

stl

I have a sequence, e.g

std::vector< Foo > someVariable;

and I want a loop which iterates through everything in it.

I could do this:

for (int i=0;i<someVariable.size();i++) {
    blah(someVariable[i].x,someVariable[i].y);
    woop(someVariable[i].z);
}

or I could do this:

for (std::vector< Foo >::iterator i=someVariable.begin(); i!=someVariable.end(); i++) {
    blah(i->x,i->y);
    woop(i->z);
}

Both these seem to involve quite a bit of repetition / excessive typing. In an ideal language I'd like to be able to do something like this:

for (i in someVariable) {
    blah(i->x,i->y);
    woop(i->z);
}

It seems like iterating through everything in a sequence would be an incredibly common operation. Is there a way to do it in which the code isn't twice as long as it should have to be?

like image 909
Angus Avatar asked Sep 26 '09 03:09

Angus


4 Answers

You could use for_each from the standard library. You could pass a functor or a function to it. The solution I like is BOOST_FOREACH, which is just like foreach in other languages. C+0x is gonna have one btw.

For example:

#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/foreach.hpp>

#define foreach BOOST_FOREACH 

void print(int v)
{
    std::cout << v << std::endl;
}

int main()
{
    std::vector<int> array;

    for(int i = 0; i < 100; ++i)
    {
        array.push_back(i);
    }

    std::for_each(array.begin(), array.end(), print); // using STL

    foreach(int v, array) // using Boost
    {
        std::cout << v << std::endl;
    }
}
like image 91
Khaled Alshaya Avatar answered Oct 06 '22 13:10

Khaled Alshaya


Not counting BOOST_FOREACH which AraK already suggested, you have the following two options in C++ today:

void function(Foo& arg){
  blah(arg.x, arg.y);
  woop(arg.z);
}

std::for_each(someVariable.begin(), someVariable.end(), function); 

struct functor {
  void operator()(Foo& arg){
    blah(arg.x, arg.y);
    woop(arg.z);
  }
};

std::for_each(someVariable.begin(), someVariable.end(), functor());

Both require you to specify the "body" of the loop elsewhere, either as a function or as a functor (a class which overloads operator()). That might be a good thing (if you need to do the same thing in multiple loops, you only have to define the function once), but it can be a bit tedious too. The function version may be a bit less efficient, because the compiler is generally unable to inline the function call. (A function pointer is passed as the third argument, and the compiler has to do some more detailed analysis to determine which function it points to)

The functor version is basically zero overhead. Because an object of type functor is passed to for_each, the compiler knows exactly which function to call: functor::operator(), and so it can be trivially inlined and will be just as efficient as your original loop.

C++0x will introduce lambda expressions which make a third form possible.

std::for_each(someVariable.begin(), someVariable.end(), [](Foo& arg){
  blah(arg.x, arg.y);
  woop(arg.z);
});

Finally, it will also introduce a range-based for loop:

for(Foo& arg : my_someVariable)
{
  blah(arg.x, arg.y);
  woop(arg.z);
}

So if you've got access to a compiler which supports subsets of C++0x, you might be able to use one or both of the last forms. Otherwise, the idiomatic solution (without using Boost) is to use for_eachlike in one of the two first examples.

like image 21
jalf Avatar answered Oct 06 '22 12:10

jalf


By the way, MSVS 2008 has a "for each" C++ keyword. Look at How to: Iterate Over STL Collection with for each.

int main() {
   int retval = 0;

   vector<int> col(3);
   col[0] = 10;
   col[1] = 20;
   col[2] = 30;

   for each( const int& c in col )
      retval += c;

   cout << "retval: " << retval << endl;
}
like image 43
Sergey Podobry Avatar answered Oct 06 '22 13:10

Sergey Podobry


Prefer algorithm calls to hand-written loops

There are three reasons:

1) Efficiency: Algorithms are often more efficient than the loops programmers produce

2) Correctness: Writing loops is more subject to errors than is calling algorithms.

3) Maintainability: Algorithm calls often yield code that is clearer and more
straightforward than the corresponding explicit loops.

like image 36
Satbir Avatar answered Oct 06 '22 12:10

Satbir