Итератор доступа в цикле BOOST_FOREACH - PullRequest
4 голосов
/ 09 июня 2009

У меня есть цикл BOOST_FOREACH для перебора списка. К сожалению, мне также нужно кэшировать итератор для определенного элемента.

typedef List::iterator savedIterator;

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

// do more stuff...     
}

Очевидно, что я могу сделать это, используя цикл list.begin () .. list.end (), но я вырос до уровня BOOST_FOREACH. Есть ли способ обойти это?

Ответы [ 3 ]

7 голосов
/ 09 июня 2009

Это невозможно, поскольку у вас нет доступа к итератору, указывающему на текущий элемент внутри цикла.

Вы можете каким-то образом получить итератор из списка, используя текущие данные об элементах, но я не знаю, стоит ли следовать этой идее, также с точки зрения производительности.

Я бы посоветовал вам использовать решение, которое вы сами предложили, с list.begin () .. list.end (), на мой взгляд, это самое простое для реализации и распознавания.

4 голосов
/ 09 июня 2009

С Boost.Foreach вы в значительной степени застряли со ссылкой на разыменованный итератор, поскольку это то, для чего предназначено Boost.Foreach: упростить доступ к элементам в диапазоне. Однако, если вы просто ищете один элемент, который соответствует критериям, вы можете попробовать 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());

Похоже, что вы хотите применить операции ко всему списку - в этом случае я бы предложил использовать что-то вроде std::min_element() или std::max_element() вместе с Boost.Iterators, например 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();
1 голос
/ 07 декабря 2009

Я удивляюсь, почему люди не делают этого:

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