Pastebin launched a little side project called HostCabi.net, check it out ;-)Don't like ads? PRO users don't see any ads ;-)
Guest

A C++ iterator adapter which wraps and hides an inner iterator and converts the iterated type

By: a guest on Feb 26th, 2012  |  syntax: None  |  size: 5.49 KB  |  hits: 22  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. MagicIterator
  2.        
  3. MagicIterator
  4.        
  5. MagicIterator
  6.        
  7. class cont_iter
  8.   : public boost::iterator_adaptor<
  9.         cont_iter                       // Derived
  10.       , std::list<Container::Item>::iterator // Base
  11.       , IInterface*                     // Value
  12.       , boost::forward_traversal_tag    // CategoryOrTraversal
  13.       , IInterface*                     // Reference :)
  14.     >
  15. {
  16.  public:
  17.     cont_iter()
  18.       : cont_iter::iterator_adaptor_() {}
  19.  
  20.     explicit cont_iter(const cont_iter::iterator_adaptor_::base_type& p)
  21.       : cont_iter::iterator_adaptor_(p) {}
  22.  
  23.  private:
  24.     friend class boost::iterator_core_access;
  25.     IInterface* dereference() { return this->base()->pObject->GetInterface(); }
  26. };
  27.        
  28. namespace detail {
  29.     template<typename T, typename U>
  30.     struct constify;
  31.  
  32.     template<typename T, typename U>
  33.     struct constify<T*, U*> {
  34.         typedef T * type;
  35.     };
  36.  
  37.     template<typename T, typename U>
  38.     struct constify<T*, U const*> {
  39.         typedef T const * type;
  40.     };
  41. }
  42.  
  43. template<typename DstType,
  44.          typename Container,
  45.          typename InputIterator>
  46. struct MagicIterator;
  47.  
  48. class Container
  49. {
  50. private:
  51.     struct Item
  52.     {
  53.         Object* pObject;
  54.     };
  55.  
  56.     std::list<Item> m_items;
  57.  
  58. public:
  59.  
  60.     // required by every Container for the iterator
  61.     typedef std::list<Item> iterator;
  62.     typedef std::list<Item> const_iterator;
  63.  
  64.     // convenience declarations
  65.     typedef MagicIterator< IInterface*, Container, iterator >
  66.         item_iterator;
  67.     typedef MagicIterator< IInterface*, Container, const_iterator >
  68.         const_item_iterator;
  69.  
  70.     item_iterator Begin();
  71.     item_iterator End();
  72. };
  73.  
  74. template<typename DstType,
  75.          typename Container = Container,
  76.          typename InputIterator = typename Container::iterator>
  77. struct MagicIterator :
  78.     // pick either const T or T, depending on whether it's a const_iterator.
  79.     std::iterator<std::input_iterator_tag,
  80.                   typename detail::constify<
  81.                            DstType,
  82.                            typename InputIterator::value_type*>::type> {
  83.     typedef std::iterator<std::input_iterator_tag,
  84.                  typename detail::constify<
  85.                           DstType,
  86.                           typename InputIterator::value_type*>::type> base;
  87.     MagicIterator():wrapped() { }
  88.     explicit MagicIterator(InputIterator const& it):wrapped(it) { }
  89.     MagicIterator(MagicIterator const& that):wrapped(that.wrapped) { }
  90.  
  91.     typename base::value_type operator*() {
  92.         return (*wrapped).pObject->GetInterface();
  93.     }
  94.  
  95.     MagicIterator& operator++() {
  96.         ++wrapped;
  97.         return *this;
  98.     }
  99.  
  100.     MagicIterator operator++(int) {
  101.         MagicIterator it(*this);
  102.         wrapped++;
  103.         return it;
  104.     }
  105.  
  106.     bool operator==(MagicIterator const& it) const {
  107.         return it.wrapped == wrapped;
  108.     }
  109.  
  110.     bool operator!=(MagicIterator const& it) const {
  111.         return !(*this == it);
  112.     }
  113.  
  114.     InputIterator wrapped;
  115. };
  116.  
  117. // now that the iterator adepter is defined, we can define Begin and End
  118. inline Container::item_iterator Container::Begin() {
  119.     return item_iterator(m_items.begin());
  120. }
  121.  
  122. inline Container::item_iterator Container::End() {
  123.     return item_iterator(m_items.end());
  124. }
  125.        
  126. for(MagicIterator<IInterface*> it = c.Begin(); it != c.End(); ++it) {
  127.     // ...
  128. }
  129.        
  130. template<typename T>
  131. class IteratorImplementation
  132. {
  133.     public:
  134.         virtual ~IteratorImplementation() = 0;
  135.  
  136.         virtual T &operator*() = 0;
  137.         virtual const T &operator*() const = 0;
  138.  
  139.         virtual Iterator<T> &operator++() = 0;
  140.         virtual Iterator<T> &operator--() = 0;
  141. };
  142.        
  143. template<typename T>
  144. class Iterator
  145. {
  146.     public:
  147.         Iterator(IteratorImplementation<T> * = 0);
  148.         ~Iterator();
  149.  
  150.         T &operator*();
  151.         const T &operator*() const;
  152.  
  153.         Iterator<T> &operator++();
  154.         Iterator<T> &operator--();
  155.  
  156.     private:
  157.         IteratorImplementation<T> *i;
  158. }
  159.  
  160. Iterator::Iterator(IteratorImplementation<T> *impl) :
  161.     i(impl)
  162. {
  163. }
  164.  
  165. Iterator::~Iterator()
  166. {
  167.     delete i;
  168. }
  169.  
  170. T &Iterator::operator*()
  171. {
  172.     if(!impl)
  173.     {
  174.         // Throw exception if you please.
  175.         return;
  176.     }
  177.  
  178.     return (*impl)();
  179. }
  180.  
  181. // etc.
  182.        
  183. class ObjectContainer
  184. {
  185.     public:
  186.         void insert(Object *o);
  187.         // ...
  188.  
  189.         Iterator<Object *> begin();
  190.         Iterator<Object *> end();
  191.  
  192.     private:
  193.         class CustomIteratorImplementation :
  194.             public IteratorImplementation<Object *>
  195.         {
  196.             public:
  197.                 // Re-implement stuff here.
  198.         }
  199. };
  200.  
  201. Iterator<Object *> ObjectContainer::begin()
  202. {
  203.     CustomIteratorImplementation *impl = new CustomIteratorImplementation();  // Wish we had C++0x's "var" here.  ;P
  204.  
  205.     return Iterator<Object *>(impl);
  206. }
  207.        
  208. template<typename T>
  209. class MagicIterator
  210. {
  211.     public:
  212.         MagicIterator(std::vector<T>::const_iterator i)
  213.         {
  214.             vector_const_iterator = i;
  215.         }
  216.  
  217.         // Reimplement similarly for more types.
  218.         MagicIterator(std::vector<T>::iterator i);
  219.         MagicIterator(std::list<T>::const_iterator i);
  220.         MagicIterator(std::list<T>::iterator i);
  221.  
  222.         // Reimplement operators here...
  223.  
  224.     private:
  225.         std::vector<T>::const_iterator vector_const_iterator;
  226.         std::vector<T>::iterator       vector_iterator;
  227.         std::list<T>::const_iterator   list_const_iterator;
  228.         std::list<T>::iterator         list_iterator;
  229. };
  230.        
  231. // C++0x
  232. template<typename T>
  233. class Iterator :
  234.     public T::iterator
  235. {
  236.     using T::iterator::iterator;
  237. };
  238.  
  239. for(Iterator<Container> i = c.begin(); i != c.end(); ++i)
  240. {
  241.     // ...
  242. }