Foreach in c++

June 17, 2010

Some people have grown up enough to use STL when teaching a computer device some new tricks. Yet they often forget why they took that road in the first place. It usually was to make their life a bit easier. To have a more firm grasp of the code in front of them.

But they still tend to go into the fears that all object oriented stuff is good, and macros are bad. This leads to spending time developing factories of factories of factories, when a simple new would often do just fine.

The same goes for the macros and templates. For some reason many cling to the belief that all should be done through the templates. In their belief they often forget that macros can provide the extra punch when used appropriately.

One example of such appropriate usage of macros is foreach macro which I created. It eases operation on STL containers: 

// Foreach.h C++ helper
// (C) 2010 Artur Sowiński <artur.sowinski@gmail.com>
// Released under MIT license as defined at
// http://pleasanthacking.com/license/

// plain vanilla iterator version
#define foreach(IT,X) for ( typeof( X->begin() ) IT = X->begin(); IT != X->end(); ++IT )
#define foreach_(IT,X) for ( typeof( X.begin() ) IT = X.begin(); IT != X.end(); ++IT )

// vanilla enforced with secure deleting of element from within the loop
#define foreachdel(IT,X) for ( typeof( X->begin() ) IT = X->begin(); typeof( IT ) IT##_bup = IT; IT != X->end(); (IT == IT##_bup) IT##_bup = ++IT : IT##_bup = IT  )
#define foreachdel_(IT,X) for ( typeof( X.begin() ) IT = X.begin(); typeof( IT ) IT##_bup = IT; IT != X.end(); (IT == IT##_bup) IT##_bup = ++IT : IT##_bup = IT  )

It sure does look unreadable, but these lines will not be seen often. When dealing with the real code you would only use it for example like this:

#include <cstdio>
#include <vector>
#include "foreach.h"

int main()
{
    // make int vector and fill it
    vector<int> k;
    for (int i=0; i<10; ++i) k.push_back(i);

    // show what the upper loop filled
    foreach_ (it, k) printf("%i ",(*it));
    printf("\n");

    // show all the data, but get rid of 4
    // http://en.wikipedia.org/wiki/Tetraphobia :)
    foreachdel_ (it, k)
    {
        if (*it == 4) it=k.erase(it);
        printf("%i ",(*it));
    }
    printf("\n");

    return 0;
}

This code will give the following output:

0 1 2 3 4 5 6 7 8 9
0 1 2 3 5 6 7 8 9

It sure beats the usual STL way, in which it would not look pretty because of the way of writing loops in STL. Also the macros take care of extra thinking, and minimize the number of potential errors. Without them you’d have to insert a condition somewhere in the second loop, to check when iterator wouldn’t be incremented when deletion occurs, since erase() method of most of the STL containers returns the next element in object. If you’d forgot about it your loop would skip elements…

This little macro saves you from all that thinking.

My foreach.h helper works on g++, no idea how it will behave in icc, but it probably will do just fine since icc is quite smart, and on msvc it will most likely break since msvc has problems with typeof(). If you’ll find a way to implement those macros on msvc let me know so others might enjoy it as well.

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 137 other followers

%d bloggers like this: