user1507133
user1507133

Reputation: 473

STL iterator loops

I wrote this code:

#define VECTOR_LOOP_V(X) for (vector<typeof(X)>::iterator it = X.begin(); it != X.end(); it++)

to make it faster to write for loops for vectors but for some reason it does not work, and when I try to compile it it gives me really, really long error message.

 test.cpp: In function ‘int main(int, char**)’:
test.cpp:20:5: error: conversion from ‘std::vector<std::basic_string<char> >::iterator {aka __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >}’ to non-scalar type ‘std::v

etc..

Upvotes: 0

Views: 2628

Answers (2)

#define VECTOR_LOOP_V(X) \
     for (vector<typeof(X)>::iterator it = X.begin(); \
          it != X.end(); it++)

How do you intend on using the macro? It looks like X is the container, in which case, the first part of the for should be something like typeof(X)::iterator (don't even know if that is legal, since typeof is not standard and have never used).

Alternatively, you can just use boost::foreach which provides a similar although a bit richer macro, with the advantage that it is safer in many respects. For example, your macro will break awfully if the argument is a function call that returns by value:

std::vector<int> f();
VECTOR_LOOP_V( f() ) {
   std::cout << *it << "\n";
}

The problem is as with almost all macros that you evaluate the arguments multiple times, and in your case it will be an iterator into one std::vector<int> and termination condition will try to compare it with an iterator from a different std::vector<int>.

Upvotes: 4

user405725
user405725

Reputation:

It doesn't work because typeof(X) yields std::vector type and so the macro expands to something like:

for (vector<std::vector<...> >::iterator it = X.begin(); it != X.end(); it++)

Also, your macro would fail if X is constant, in which case const_iterator should be used. There are tons of other problems, but at any rate, what you were trying to do is something like this:

#define VECTOR_LOOP_V(X) \
    for (typeof(X.begin()) it = X.begin(), eit = X.end(); it != eit; ++it)

.. and here is some usage example:

#include <vector>
#include <iostream>

#define VECTOR_LOOP_V(X) \
    for (typeof(X.begin()) it = X.begin(), eit = X.end(); it != eit; ++it)

int main()
{
    std::vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);
    VECTOR_LOOP_V(v) {
        std::cout << *it << std::endl;
    }
}

Note, however, that typeof is not a standard C++ (see this Q/A).

All in all, you are better off using BOOST_FOREACH (or at least see how it is implemented there) or C++11 range-based for loop.

P.S.: Do not use the STL abbreviation unless you really mean STL and not C++ Standard Library (which you can refer to as, say, stdlib).

Upvotes: 3

Related Questions