Fast and flexible iterator for abstract class

前端 未结 1 1079
别那么骄傲
别那么骄傲 2021-01-21 22:26

In order to traverse grids with data in a fast and flexible way I set up an abstract, templated GridDataStructure class. The data should be accessed by STL iterators. When someo

相关标签:
1条回答
  • 2021-01-21 23:19

    In the solution, begin and end don't need to be virtual, because they just call BaseIteratorImpl::begin and BaseIteratorImpl::end which are virtual.

    In your specific case, you could just make begin and end virtual and not do any forwarding and it would be able to do what you want. The solution you pointed to is if you want different style iterators over the same structure, not just structure-iterator pairings which it seems you want.

    EDIT: Here's something to start with (not tested or even compiled) -- might not compile and will leak (write destructors, copy ctors, op=, where you need to) -- just to get you started on the idea.

    template <class T>
    class GridIteratorImplBase {
       public:
          virtual GridIteratorImplBase<T>& operator++() = 0;
          virtual T& operator*() = 0;
    };
    
    template <class T>
    class GridIterator {
       private:
          GridIteratorImplBase<T> *baseImpl;
       public:
          GridIterator(GridIteratorImplBase<T> *b) :baseImpl(b) {}
          GridIterator& operator++() { baseImpl->operator++(); return *this;}
          T& operator*() { return baseImpl->operator*(); }
    
    
      // you need to write a dtor, copy ctor and op= or this will leak
      // copy ctor and op= need to make new objects that are copies of baseImpl, dtor needs to delete -- make sure not to share baseImpl between two GridIterator objects
    };
    
    
    template <class T>
    class Grid {
       virtual GridIterator<T> begin() = 0;
       virtual GridIterator<T> end() = 0;
    };
    
    
    template <class T>
    class GridUniform {
    
      template <class T>
      class GridUniformIterator : GridIteratorImplBase<T>
          private T* current;
       public:
          GridUniformIterator(T* c) : current(c) {}
          virtual GridIteratorImplBase<T>& operator++() { current++; return *this; }
          virtual T& operator*() { return *current; }
      };
    
      GridIterator<T> begin() { 
          GridIterator<T> iter(new GridUniformIterator(gridData)); 
          return iter; 
      }
      GridIterator<T> end() { 
          GridIterator<T> iter(new GridUniformIterator(gridData+size));
          return iter; 
      }
    
    
      private:
        T* gridData;
        int size;
    };
    

    I typed this directly in to the text area of this answer -- not a compiler. It's meant to give you the idea so you can get started.

    1. begin and end are supposed to create iterators
    2. iterators need to be able to be copy constructed and have operator= called on them. If you try to have one base class for them, they will get casted to the base, so you can't use virtual for them
    3. To get around #2, you make iterators just hold onto a pointer to a base class of an iterator implementation.
    0 讨论(0)
提交回复
热议问题