【问题标题】:Create Iterator to C++ container that returns a std::pair创建迭代器到返回 std::pair 的 C++ 容器
【发布时间】:2013-11-08 11:21:47
【问题描述】:

我正在尝试在 C++ 中实现一个容器,该容器使用平面数组来存储数据,但会成对地迭代该数据。现在我可以轻松地更改实现,使容器包含std::pair 的向量,但是我想遍历从元素 0 或元素 1 开始的对。

为了说明我想要实现的目标,如果我的底层数组如下所示: 1,2,3,4,5,6,7,8

我想定义两个迭代器,一个返回对: (1,2), (3,4), (5,6), (7,8) 以及返回对的第二个迭代器: (2,3), (4,5), (6,7)

在允许迭代器的元素作为底层数组的引用的同时这样做是否可行?

【问题讨论】:

    标签: c++ iterator


    【解决方案1】:

    可以编写自己的迭代器,它对元素进行迭代。以下问题显示了有关如何完成的一些解释: Custom Iterator in C++.

    然后您可以将所需的值作为 std::pair 返回并迭代到下一个元素对(通过将计数器增加 2)。

    【讨论】:

      【解决方案2】:

      Boost 库有Iterator Adaptor,它允许您包装其他迭代器类型并更改或调整它们的功能。以下是您如何将其用于您的目的:

      #include <boost/iterator/iterator_adaptor.hpp>
      #include <vector>
      
      struct iterator :
          public boost::iterator_adaptor<
              iterator,                    // the name of our class, see docs for details
              std::vector<int>::iterator,  // underlying base iterator
              std::pair<int&, int&>,       // our value type
              boost::forward_traversal_tag // the category you wish to give it
          >
      {
           // need this to convert from vector::iterator to ours
          explicit iterator(std::vector<int>::iterator i)
              : iterator::iterator_adaptor_(i) {}
      
          value_type operator*()
          {
              return value_type(
                  *base_reference(),
                  *(base_reference()+1)
              );
          }
      };
      

      使用示例:

      std::vector<int> v {1,2,3,4};
      iterator it(v.begin());
      ++it;
      (*it).first = 0;  // TODO: operator->
      (*it).second = 0;
      
      for (int i : v) std::cout << i << ' '; // prints 1 0 0 4
      

      您还需要覆盖比较以正确处理结束条件等。希望对您有所帮助。

      【讨论】:

        【解决方案3】:

        只是想我会在我的代码中输入我实际使用的内容。我不想按照@jrok 的建议使用 boost,但他们回答中的 std::pair&lt;int&amp;, int&amp;&gt; 类型给了我所需的提示。

        下面是我构建的使用两个迭代器的类。 RepeatIterator 返回从基础数据中偶数索引开始的对,SpacerIterator 返回从奇数索引开始的对。

        class RepeatArray {
            typedef std::vector<int> storage_t;
        
        public:
            class RepeatIterator {
            public:
                typedef RepeatIterator self_t;
                typedef int value_t;
                typedef int& reference_t;
                typedef int* pointer_t;
                typedef std::pair<reference_t, reference_t> return_t;
        
                RepeatIterator(storage_t::iterator input) : current_pos(input){}
        
                return_t operator *() {
                    return return_t(*(current_pos), *(current_pos + 1 ));
                }
        
                self_t operator++() { self_t i = *this; current_pos += 2; return i; }
                self_t operator++(int junk) { current_pos+=2; return *this; }
        
        
                bool operator==(const self_t& rhs) { return current_pos == rhs.current_pos; }
                bool operator!=(const self_t& rhs) { return current_pos != rhs.current_pos; }
                bool operator<(const self_t& rhs) { return current_pos < rhs.current_pos; }
                bool operator<=(const self_t& rhs) { return current_pos <= rhs.current_pos; }
                bool operator>(const self_t& rhs) { return current_pos > rhs.current_pos; }
                bool operator>=(const self_t& rhs) { return current_pos >= rhs.current_pos; }
        
            private:
                storage_t::iterator current_pos;
            };
        
            class SpacerIterator {
            public:
                typedef SpacerIterator self_t;
                typedef int value_t;
                typedef int& reference_t;
                typedef int* pointer_t;
                typedef std::pair<reference_t, reference_t> return_t;
        
                SpacerIterator(storage_t::iterator input) : current_pos(input){}
        
                return_t operator *() {
                    return return_t(*(current_pos), *(current_pos + 1 ));
                }
        
                self_t operator++() { self_t i = *this; current_pos += 2; return i; }
                self_t operator++(int junk) { current_pos+=2; return *this; }
        
                bool operator==(const self_t& rhs) { return current_pos == rhs.current_pos; }
                bool operator!=(const self_t& rhs) { return current_pos != rhs.current_pos; }
                bool operator<(const self_t& rhs) { return current_pos < rhs.current_pos; }
                bool operator<=(const self_t& rhs) { return current_pos <= rhs.current_pos; }
                bool operator>(const self_t& rhs) { return current_pos > rhs.current_pos; }
                bool operator>=(const self_t& rhs) { return current_pos >= rhs.current_pos; }
        
        
            private:
                storage_t::iterator current_pos;
            };
        
            void add(int start, int end) {
                positions.push_back(start);
                positions.push_back(end);
            }
        
            void dump() {
                for (auto i : positions) {
                    std::cout <<i<<",";
                }
                std::cout <<std::endl;
            }
        
            RepeatIterator repeatBegin(){return RepeatIterator(positions.begin());}
            RepeatIterator repeatEnd(){return RepeatIterator(positions.end());}
        
            SpacerIterator spacerBegin(){return SpacerIterator(positions.begin() + 1);}
            SpacerIterator spacerEnd(){return SpacerIterator(positions.end() - 1);}
        
        protected:
            storage_t positions;
        };
        

        然后是使用clang++ -std=c++0x -o testRepeatArray RepeatArray.cpp编译的测试程序

        int main() {
            RepeatArray r = RepeatArray();
            r.add(1,3);
            r.add(7,12);
            std::cout<<"original:"<<std::endl;
            r.dump();
        
            std::cout << "Testing Repeat iterator:"<<std::endl;
            for (RepeatArray::RepeatIterator it2 = r.repeatBegin(); it2 != r.repeatEnd(); ++it2) {
                std::cout << (*it2).first <<","<< (*it2).second << std::endl;
            }
            std::cout << "Testing Spacer iterator:"<<std::endl;
            for (RepeatArray::SpacerIterator it3 = r.spacerBegin(); it3 != r.spacerEnd(); ++it3) {
                std::cout << (*it3).first <<","<< (*it3).second << std::endl;
            }
        
            std::cout<<"Testing modification:"<<std::endl;
        
            RepeatArray::RepeatIterator it = r.repeatBegin();
            (*it).first = 0;
            (*it).second = 123;
        
            r.dump();
            return 0;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-03-04
          • 2012-11-24
          • 2019-06-06
          • 2012-04-27
          • 1970-01-01
          • 1970-01-01
          • 2013-09-04
          • 2018-04-08
          相关资源
          最近更新 更多