File indexing completed on 2024-11-24 04:52:54

0001 /* Copyright (C) 2015 J. C. Moyer, http://stackoverflow.com/a/33851951/2245623
0002 
0003    Licensed under CC-BY-SA 3.0 as per stackoverflow.com's footer. This is GPLv3 compatible.
0004 */
0005 
0006 #pragma once
0007 
0008 #include <iterator>
0009 
0010 namespace Common {
0011 
0012 template <class Iterator>
0013 class stashing_reverse_iterator :
0014   public std::iterator<
0015     typename std::iterator_traits<Iterator>::iterator_category,
0016     typename std::iterator_traits<Iterator>::value_type,
0017     typename std::iterator_traits<Iterator>::difference_type,
0018     typename std::iterator_traits<Iterator>::pointer,
0019     typename std::iterator_traits<Iterator>::reference
0020   > {
0021   typedef std::iterator_traits<Iterator> traits_type;
0022 public:
0023   typedef Iterator iterator_type;
0024   typedef typename traits_type::difference_type difference_type;
0025   typedef typename traits_type::reference       reference;
0026   typedef typename traits_type::pointer         pointer;
0027 
0028   stashing_reverse_iterator() : current() {}
0029 
0030   explicit stashing_reverse_iterator(Iterator x) : current(x) {}
0031 
0032   template <class U>
0033   stashing_reverse_iterator(const stashing_reverse_iterator<U>& u) : current(u.current) {}
0034 
0035   template <class U>
0036   stashing_reverse_iterator& operator=(const stashing_reverse_iterator<U>& u) {
0037     current = u.base();
0038     return *this;
0039   }
0040 
0041   Iterator base() const {
0042     return current;
0043   }
0044 
0045   // Differs from reverse_iterator::operator*:
0046   // 1. const qualifier removed
0047   // 2. current iterator is stored in a member field to ensure references are
0048   //    always valid after this function returns
0049   reference operator*() {
0050     deref_tmp = current;
0051     --deref_tmp;
0052     return *deref_tmp;
0053   }
0054 
0055   pointer operator->() {
0056     return std::addressof(operator*());
0057   }
0058 
0059   stashing_reverse_iterator& operator++() {
0060     --current;
0061     return *this;
0062   }
0063 
0064  stashing_reverse_iterator operator++(int) {
0065     stashing_reverse_iterator tmp = *this;
0066     --current;
0067     return tmp;
0068   }
0069 
0070   stashing_reverse_iterator& operator--() {
0071     ++current;
0072     return *this;
0073   }
0074 
0075   stashing_reverse_iterator operator--(int) {
0076     stashing_reverse_iterator tmp = *this;
0077     ++current;
0078     return tmp;
0079   }
0080 
0081   stashing_reverse_iterator  operator+ (difference_type n) const {
0082     return stashing_reverse_iterator(current - n);
0083   }
0084 
0085   stashing_reverse_iterator& operator+=(difference_type n) {
0086     current -= n;
0087     return *this;
0088   }
0089 
0090   stashing_reverse_iterator  operator- (difference_type n) const {
0091     return stashing_reverse_iterator(current + n);
0092   }
0093 
0094   stashing_reverse_iterator& operator-=(difference_type n) {
0095     current += n;
0096     return *this;
0097   }
0098 
0099   // Differs from reverse_iterator::operator[]:
0100   // 1. const qualifier removed because this function makes use of operator*
0101   reference operator[](difference_type n) {
0102     return *(*this + n);
0103   }
0104 
0105 protected:
0106   Iterator current;
0107 private:
0108   Iterator deref_tmp;
0109 };
0110 
0111 template <class Iterator1, class Iterator2>
0112 bool operator==(
0113   const stashing_reverse_iterator<Iterator1>& x,
0114   const stashing_reverse_iterator<Iterator2>& y)
0115 { return x.base() == y.base(); }
0116 
0117 template <class Iterator1, class Iterator2>
0118 bool operator<(
0119   const stashing_reverse_iterator<Iterator1>& x,
0120   const stashing_reverse_iterator<Iterator2>& y)
0121 { return x.base() > y.base(); }
0122 
0123 template <class Iterator1, class Iterator2>
0124 bool operator!=(
0125   const stashing_reverse_iterator<Iterator1>& x,
0126   const stashing_reverse_iterator<Iterator2>& y)
0127 { return !(x.base() == y.base()); }
0128 
0129 template <class Iterator1, class Iterator2>
0130 bool operator>(
0131   const stashing_reverse_iterator<Iterator1>& x,
0132   const stashing_reverse_iterator<Iterator2>& y)
0133 { return x.base() < y.base(); }
0134 
0135 template <class Iterator1, class Iterator2>
0136 bool operator>=(
0137   const stashing_reverse_iterator<Iterator1>& x,
0138   const stashing_reverse_iterator<Iterator2>& y)
0139 { return x.base() <= y.base(); }
0140 
0141 template <class Iterator1, class Iterator2>
0142 bool operator<=(
0143   const stashing_reverse_iterator<Iterator1>& x,
0144   const stashing_reverse_iterator<Iterator2>& y)
0145 { return x.base() >= y.base(); }
0146 
0147 template <class Iterator1, class Iterator2>
0148 auto operator-(
0149   const stashing_reverse_iterator<Iterator1>& x,
0150   const stashing_reverse_iterator<Iterator2>& y) -> decltype(y.base() - x.base())
0151 { return y.base() - x.base(); }
0152 
0153 template <class Iterator>
0154 stashing_reverse_iterator<Iterator> operator+(
0155   typename stashing_reverse_iterator<Iterator>::difference_type n,
0156   const stashing_reverse_iterator<Iterator>& x)
0157 { return stashing_reverse_iterator<Iterator>(x.base() - n); }
0158 
0159 template <class Iterator>
0160 stashing_reverse_iterator<Iterator> make_stashing_reverse_iterator(Iterator i)
0161 { return stashing_reverse_iterator<Iterator>(i); }
0162 
0163 }