Wrap iteration handle for use in range-based for-loops

爷,独闯天下 提交于 2019-12-23 19:34:05

问题


I use an API that comes with an iteration functionality using a void* handle.

void* handle = BrowseInit();
while (BrowseGetNext(handle))
{
  // ...
  int x = BrowseGetData(handle);
}
BrowseFree(handle);

How would I go about wrapping this into a C++11 iterator for use in range-based for-loops? Since the value of the handle doesn't actually change, I need some trickery in operator != ().

class Iterator
{
public:

  friend class it;
  class it
  {
  public:

    it(Iterator* data) : _data(data) { }
    bool operator != (const it& other) const
    {
      // what should I put in here?
    }
    const it& operator ++ ()
    {
      BrowseGetNext(_data->_handle);
    }
    int operator * () const
    {
      return BrowseGetData(_data->_handle);
    }

  private:
    Iterator* _data;
  };

  Iterator() : _handle(BrowseInit()) { }
  ~Iterator() 
  {
    BrowseFree(_handle);
  }

  it begin() const
  {
    return it(this);
  }
  it end() const
  {
    return it(nullptr);
  }

private:

  void* _handle;
};

回答1:


This should work.

class Iterator
{
   public:

      friend class it;
      class it
      {
         public:

            // Constructor for begin().
            it(Iterator* data) : _data(data), index_(0) { }

            // Constructor for end().
            it(Iterator* data, int) : _data(data), index_(-1) { }

            bool operator != (const it& other) const
            {
               return !(*this == other);
            }
            bool operator == (const it& other) const
            {
               return ( this->_data == other._data && this->_index == rhs._index );
            }

            const it& operator ++ ()
            {
               // Increment the index if there's more data.
               // Otherwise, set it to -1.
               if ( BrowseGetNext(_data->_handle) )
               {
                  ++index_;
               }
               else
               {
                  index_ = -1;
               }
            }

            int operator * () const
            {
               return BrowseGetData(_data->_handle);
            }

         private:
            Iterator* _data;
            int _index;
      };

      Iterator() : _handle(BrowseInit()) { }
      ~Iterator() 
      {
         BrowseFree(_handle);
      }

      it begin() const
      {
         return it(this);
      }
      it end() const
      {
         return it(this, 0);
      }

   private:

      void* _handle;
};

Update: Setup iterator_traits for it

template <> std::iterator_traits<Iterator::it>
{
    typedef int difference_type;
    typedef int value_type;
    typedef int* pointer;
    typedef int& reference;
    typedef std::forward_iterator_tag iterator_category;
};

Thanks for the suggestion, Yakk.

Update 2

Instead of specializing std::iterator for Iterator::it, derive Iterator::it from std::iterator.

class it : public std::iterator<std::forward_iterator_tag, int, int>
{
....
};


来源:https://stackoverflow.com/questions/24892998/wrap-iteration-handle-for-use-in-range-based-for-loops

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!