简体   繁体   English

C ++迭代器在向量中的某些元素上

[英]C++ iterator over certain elements in vector

Please forgive me if this is a trivial question, I'm just learning C++ and try to wrap my head around certain concepts. 如果这是一个微不足道的问题,请原谅我,我只是学习C ++并尝试围绕某些概念。 Especially when it comes to iterators, I'm completely lost. 特别是在谈到迭代器时,我完全迷失了。

Say I have a custom class representing some data structure, and one of its members is a vector of integers. 假设我有一个表示某种数据结构的自定义类,其中一个成员是一个整数向量。 I want to write a bidirectional iterator for that class, which outputs only the EVEN numbers in the vector. 我想为该类编写一个双向迭代器,它只输出向量中的偶数。 Is there an easy and instructive way? 有一种简单而有教育意义的方式吗? I'd prefer not using libraries other than STL. 我不想使用STL以外的库。

Not sure making your own iterator is easy. 不确定自己的迭代器是否容易。 But probably the best is to use a conditional for_each functions. 但最好的方法是使用条件for_each函数。

std::for_each does an operation on every elements. std::for_each对每个元素执行操作。 It's pretty easy to create a for_each_if doing an operation on some specific elements. 创建一个for_each_if对某些特定元素进行操作非常容易。 For instance, program below only prints even numbers from the vector (4, 6 and 8). 例如,下面的程序只打印矢量(4,6和8)中的偶数。

#include <iostream>
#include <vector>

using namespace std;

struct is_even {
  typedef bool return_type;
  bool operator() (const int& value) {return (value%2)==0; }
};

struct doprint {
  bool operator() (const int& value) { std::cout << value << std::endl; }
};

template <class InputIterator, class Predicate, class Function> 
void for_each_if(InputIterator first, InputIterator last, Function f, Predicate pred) 
{ 
    while ( first != last )
    {  
        if (pred (*first)) 
            f(*first++);  
        else 
            first ++; 
    }
}

int main()
{
   std::vector<int> v;
   v.push_back( 4 );
   v.push_back( 5 );
   v.push_back( 6 );
   v.push_back( 8 );

   for_each_if( v.begin(), v.end(), doprint(), is_even());

   return 0;
}

Going by your requirements, deriving from vector::iterator would probably be the easiest: 根据您的要求,从vector::iterator派生可能是最简单的:

class my_iterator : private std::vector<int>::iterator {
    typedef std::vector<int>::iterator base;
    base m_base_end;   // Stores the real end iterator of the internal vector.
                       // We need it so that the even/odd checking code
                       // doesn't run off the end of the vector
                       // (initialize it in a constructor, omitted here for
                       // brevity).
public:

    using base::operator*;
    using base::operator->;
    // etc. for other members...

    // except for increment:

    my_iterator& operator++()
    {
        do {
            base::operator++();
        } while( static_cast<base&>(*this) != m_base_end
                 && base::operator*() % 2 );
        return *this;
    }

    my_iterator operator++(int)
    {
        my_iterator temp;
        operator++();
        return temp;
    }

    // TODO: decrement and other arithmetic operators
};

It's still quite a bit of boilerplate, and you'll also want to do the same for const_iterator (I'd probably make the above class a template to make it easier). 它仍然是相当多的样板,你也想为const_iterator做同样的事情(我可能会让上面的类成为一个模板以使其更容易)。

Consider Boost for this - it has filter_iterator just for this purpose. 考虑一下Boost - 它只是为了这个目的而有filter_iterator There's also iterator_adaptor if that doesn't suit you. 如果这不适合你,还有iterator_adaptor


#include <vector>
#include <iostream>

class X {

public:

  class EvenIterator {
  public:
    EvenIterator(std::vector<int>::iterator it, std::vector&ltint>::iterator end) : it(it), end(end) {
      while (true) {
        if (isEven(*it)) {
          break;
        } else if (it == end) {
          break;
        }
        it++;
      }
    }

    bool operator != (const EvenIterator& evenIt) {
      return evenIt.it != this->it;
    }

    int operator * () {
      return *it;
    }

    EvenIterator operator ++ () {
      while (true) {
        it++;
        if (isEven(*it)) {
          return EvenIterator(it, end);
        } else if (it == end) {
          return EvenIterator(it, end);
        }
      }
    }
  private:
    std::vector&ltint>::iterator it;    
    std::vector&ltint>::iterator end;    
  };

  static bool isEven(int number) {
    return number % 2 == 0;
  }

  void add(int number) {
    v.push_back(number);
  }

  EvenIterator evenBegin() {
    return EvenIterator(v.begin(), v.end());
  }

  EvenIterator evenEnd() {
    return EvenIterator(v.end(), v.end());
  }

private:
  std::vector&ltint> v;

};

int main() {
  X x;
  x.add(1);
  x.add(2);
  x.add(3);
  x.add(2);
  x.add(2);
  x.add(31);
  x.add(56);
  x.add(101);

  for (X::EvenIterator it = x.evenBegin(); it != x.evenEnd(); ++it){
    std::cout << *it << std::endl; // only prints the even numbers
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM