1 // 2 // Copyright 2013 Francisco Jerez 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 // OTHER DEALINGS IN THE SOFTWARE. 21 // 22 23 #ifndef CLOVER_UTIL_ADAPTOR_HPP 24 #define CLOVER_UTIL_ADAPTOR_HPP 25 26 #include <iterator> 27 28 #include "util/tuple.hpp" 29 #include "util/pointer.hpp" 30 #include "util/functional.hpp" 31 32 namespace clover { 33 namespace detail { 34 /// 35 /// Implementation of the iterator concept that transforms the 36 /// value of the source iterators \a Is on dereference by use of 37 /// a functor \a F. 38 /// 39 /// The exact category of the resulting iterator should be the 40 /// least common denominator of the source iterator categories. 41 /// 42 template<typename F, typename... Is> 43 class iterator_adaptor { 44 public: 45 typedef std::forward_iterator_tag iterator_category; 46 typedef typename std::result_of< 47 F(typename std::iterator_traits<Is>::reference...) 48 >::type reference; 49 typedef typename std::remove_reference<reference>::type value_type; 50 typedef pseudo_ptr<value_type> pointer; 51 typedef std::ptrdiff_t difference_type; 52 iterator_adaptor()53 iterator_adaptor() { 54 } 55 iterator_adaptor(F f,std::tuple<Is...> && its)56 iterator_adaptor(F f, std::tuple<Is...> &&its) : 57 f(f), its(std::move(its)) { 58 } 59 60 reference operator *() const61 operator*() const { 62 return tuple::apply(f, tuple::map(derefs(), its)); 63 } 64 65 iterator_adaptor & operator ++()66 operator++() { 67 tuple::map(preincs(), its); 68 return *this; 69 } 70 71 iterator_adaptor operator ++(int)72 operator++(int) { 73 auto jt = *this; 74 ++*this; 75 return jt; 76 } 77 78 bool operator ==(const iterator_adaptor & jt) const79 operator==(const iterator_adaptor &jt) const { 80 return its == jt.its; 81 } 82 83 bool operator !=(const iterator_adaptor & jt) const84 operator!=(const iterator_adaptor &jt) const { 85 return its != jt.its; 86 } 87 88 pointer operator ->() const89 operator->() const { 90 return { **this }; 91 } 92 93 iterator_adaptor & operator --()94 operator--() { 95 tuple::map(predecs(), its); 96 return *this; 97 } 98 99 iterator_adaptor operator --(int)100 operator--(int) { 101 auto jt = *this; 102 --*this; 103 return jt; 104 } 105 106 iterator_adaptor & operator +=(difference_type n)107 operator+=(difference_type n) { 108 tuple::map(advances_by(n), its); 109 return *this; 110 } 111 112 iterator_adaptor & operator -=(difference_type n)113 operator-=(difference_type n) { 114 tuple::map(advances_by(-n), its); 115 return *this; 116 } 117 118 iterator_adaptor operator +(difference_type n) const119 operator+(difference_type n) const { 120 auto jt = *this; 121 jt += n; 122 return jt; 123 } 124 125 iterator_adaptor operator -(difference_type n) const126 operator-(difference_type n) const { 127 auto jt = *this; 128 jt -= n; 129 return jt; 130 } 131 132 difference_type operator -(const iterator_adaptor & jt) const133 operator-(const iterator_adaptor &jt) const { 134 return std::get<0>(its) - std::get<0>(jt.its); 135 } 136 137 reference operator [](difference_type n) const138 operator[](difference_type n) const { 139 return *(*this + n); 140 } 141 142 bool operator <(iterator_adaptor & jt) const143 operator<(iterator_adaptor &jt) const { 144 return *this - jt < 0; 145 } 146 147 bool operator >(iterator_adaptor & jt) const148 operator>(iterator_adaptor &jt) const { 149 return *this - jt > 0; 150 } 151 152 bool operator >=(iterator_adaptor & jt) const153 operator>=(iterator_adaptor &jt) const { 154 return !(*this < jt); 155 } 156 157 bool operator <=(iterator_adaptor & jt) const158 operator<=(iterator_adaptor &jt) const { 159 return !(*this > jt); 160 } 161 162 protected: 163 F f; 164 std::tuple<Is...> its; 165 }; 166 167 template<typename F, typename... Is> 168 iterator_adaptor<F, Is...> operator +(typename iterator_adaptor<F,Is...>::difference_type n,const iterator_adaptor<F,Is...> & jt)169 operator+(typename iterator_adaptor<F, Is...>::difference_type n, 170 const iterator_adaptor<F, Is...> &jt) { 171 return (jt + n); 172 } 173 174 template<typename F, typename... Is> 175 iterator_adaptor<F, Is...> operator -(typename iterator_adaptor<F,Is...>::difference_type n,const iterator_adaptor<F,Is...> & jt)176 operator-(typename iterator_adaptor<F, Is...>::difference_type n, 177 const iterator_adaptor<F, Is...> &jt) { 178 return (jt - n); 179 } 180 } 181 } 182 183 #endif 184