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 }