Roddy
Roddy

Reputation: 68074

Access Iterator in BOOST_FOREACH loop

I have a BOOST_FOREACH loop to iterate over a list. Unfortunately, I also need to cache an iterator to a particular item.

typedef List::iterator savedIterator;

BOOST_FOREACH(Item &item, list)
{
// stuff...
  if (condition)
    savedIterator = &item; // this won't work

// do more stuff...     
}

Obviously I can do this using a list.begin()..list.end() for loop, but I've grown to like BOOST_FOREACH. Is there a way round this?

Upvotes: 4

Views: 6087

Answers (3)

Tom Harada
Tom Harada

Reputation:

i kind of wonder why people don't do this:

#define foreach(iter_type, iter, collection) \
 for (iter_type iter = collection.begin(); iter != collection.end(); ++iter)

Upvotes: 1

Dean Michael
Dean Michael

Reputation: 3496

With Boost.Foreach, you're pretty much stuck with the reference to the dereferenced iterator since this is what Boost.Foreach was designed to do: simplify access to the elements in a range. However, if you're just looking for a single element that fits a criteria you might want to try std::find_if():

struct criteria {
  template <class T>
  bool operator()(T const & element) const {
    return (element /* apply criteria... */)? true : false;
  }
};

// somewhere else
List::iterator savedIterator =
  std::find_if(list.begin(), list.end(), criteria());

It also looks like you want to apply operations on the whole list -- in which case I'll suggest using something like std::min_element() or std::max_element() along with Boost.Iterators like boost::transform_iterator.

struct transformation {
  typedef int result_type;
  template <class T>
  int operator()(T const & element) const {
    // stuff
    int result = 1;
    if (condition) result = 0;
    // more stuff
    return result;
  }
};

// somewhere else
List::iterator savedIterator =
  std::min_element(
     boost::make_transform_iterator(list.begin(), transformation()),
     boost::make_transform_iterator(list.end(), transformation()),
  ).base();

Upvotes: 4

Kosi2801
Kosi2801

Reputation: 23145

This is not possible, as you do not have access to an iterator pointing to the current item inside the loop.

You could fetch an iterator from the list somehow using the current items data but I don't know if this is a good idea to follow, also performance-wise.

I'd suggest you use the solution you already proposed yourself with list.begin() .. list.end(), this is in my opinion the easiest to implement and recognize.

Upvotes: 8

Related Questions