【问题标题】:Access Iterator in BOOST_FOREACH loop在 BOOST_FOREACH 循环中访问迭代器
【发布时间】:2010-11-01 10:53:57
【问题描述】:

我有一个 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() for 循环来做到这一点,但我已经越来越喜欢 BOOST_FOREACH。有没有办法解决这个问题?

【问题讨论】:

    标签: c++ boost iterator foreach


    【解决方案1】:

    这是不可能的,因为您无法访问指向循环内当前项目的迭代器。

    您可以使用当前项目数据以某种方式从列表中获取迭代器,但我不知道这是否是一个好主意,也是性能方面的。

    我建议你使用你自己已经提出的解决方案 list.begin() .. list.end(),我认为这是最容易实现和识别的。

    【讨论】:

      【解决方案2】:

      使用 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::transform_iterator 之类的 Boost.Iterators。

      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();
      

      【讨论】:

      • 赞成,但只是因为它提醒我有时我是多么讨厌 C++。
      【解决方案3】:

      我有点想知道为什么人们不这样做:

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

      【讨论】:

      • 如果collection 是一个有副作用的表达式怎么办?您的宏将对其进行两次评估。此外,传统的 foreach 的全部意义在于直接获取值,而完全不会与迭代器(及其冗长笨拙的类型名称)发生冲突。
      • 关于集合是否是表达式的好点。在这种情况下,评估表达式,然后将其作为参考传递给 foreach。 collection_type& c = foreach(iter_type, it, c)... 访问迭代器的好处是灵活性(例如,这篇文章的问题)。我不认为要付出这么大的代价。但也许这只是我的特殊风格......
      • BOOST_FOREACH 并不像你想象的那么简单。请阅读那些文章例如,collection 只是没有迭代器的数组怎么样? cplusplus.bordoon.com/boost_foreach_techniques.htmlartima.com/cppsource/foreach.html(BOOST_FOREACH的作者写了这篇文章)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-10
      相关资源
      最近更新 更多