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/compat.hpp" 29 #include "util/tuple.hpp" 30 #include "util/pointer.hpp" 31 #include "util/functional.hpp" 32 33 namespace clover { 34 namespace detail { 35 /// 36 /// Implementation of the iterator concept that transforms the 37 /// value of the source iterators \a Is on dereference by use of 38 /// a functor \a F. 39 /// 40 /// The exact category of the resulting iterator should be the 41 /// least common denominator of the source iterator categories. 42 /// 43 template<typename F, typename... Is> 44 class iterator_adaptor { 45 public: 46 typedef std::forward_iterator_tag iterator_category; 47 typedef typename invoke_result< 48 F, typename std::iterator_traits<Is>::reference... 49 >::type reference; 50 typedef typename std::remove_reference<reference>::type value_type; 51 typedef pseudo_ptr<value_type> pointer; 52 typedef std::ptrdiff_t difference_type; 53 iterator_adaptor()54 iterator_adaptor() { 55 } 56 iterator_adaptor(F f,std::tuple<Is...> && its)57 iterator_adaptor(F f, std::tuple<Is...> &&its) : 58 f(f), its(std::move(its)) { 59 } 60 61 reference operator *() const62 operator*() const { 63 return tuple::apply(f, tuple::map(derefs(), its)); 64 } 65 66 iterator_adaptor & operator ++()67 operator++() { 68 tuple::map(preincs(), its); 69 return *this; 70 } 71 72 iterator_adaptor operator ++(int)73 operator++(int) { 74 auto jt = *this; 75 ++*this; 76 return jt; 77 } 78 79 bool operator ==(const iterator_adaptor & jt) const80 operator==(const iterator_adaptor &jt) const { 81 return its == jt.its; 82 } 83 84 bool operator !=(const iterator_adaptor & jt) const85 operator!=(const iterator_adaptor &jt) const { 86 return its != jt.its; 87 } 88 89 pointer operator ->() const90 operator->() const { 91 return { **this }; 92 } 93 94 iterator_adaptor & operator --()95 operator--() { 96 tuple::map(predecs(), its); 97 return *this; 98 } 99 100 iterator_adaptor operator --(int)101 operator--(int) { 102 auto jt = *this; 103 --*this; 104 return jt; 105 } 106 107 iterator_adaptor & operator +=(difference_type n)108 operator+=(difference_type n) { 109 tuple::map(advances_by(n), its); 110 return *this; 111 } 112 113 iterator_adaptor & operator -=(difference_type n)114 operator-=(difference_type n) { 115 tuple::map(advances_by(-n), its); 116 return *this; 117 } 118 119 iterator_adaptor operator +(difference_type n) const120 operator+(difference_type n) const { 121 auto jt = *this; 122 jt += n; 123 return jt; 124 } 125 126 iterator_adaptor operator -(difference_type n) const127 operator-(difference_type n) const { 128 auto jt = *this; 129 jt -= n; 130 return jt; 131 } 132 133 difference_type operator -(const iterator_adaptor & jt) const134 operator-(const iterator_adaptor &jt) const { 135 return std::get<0>(its) - std::get<0>(jt.its); 136 } 137 138 reference operator [](difference_type n) const139 operator[](difference_type n) const { 140 return *(*this + n); 141 } 142 143 bool operator <(iterator_adaptor & jt) const144 operator<(iterator_adaptor &jt) const { 145 return *this - jt < 0; 146 } 147 148 bool operator >(iterator_adaptor & jt) const149 operator>(iterator_adaptor &jt) const { 150 return *this - jt > 0; 151 } 152 153 bool operator >=(iterator_adaptor & jt) const154 operator>=(iterator_adaptor &jt) const { 155 return !(*this < jt); 156 } 157 158 bool operator <=(iterator_adaptor & jt) const159 operator<=(iterator_adaptor &jt) const { 160 return !(*this > jt); 161 } 162 163 protected: 164 F f; 165 std::tuple<Is...> its; 166 }; 167 168 template<typename F, typename... Is> 169 iterator_adaptor<F, Is...> operator +(typename iterator_adaptor<F,Is...>::difference_type n,const iterator_adaptor<F,Is...> & jt)170 operator+(typename iterator_adaptor<F, Is...>::difference_type n, 171 const iterator_adaptor<F, Is...> &jt) { 172 return (jt + n); 173 } 174 175 template<typename F, typename... Is> 176 iterator_adaptor<F, Is...> operator -(typename iterator_adaptor<F,Is...>::difference_type n,const iterator_adaptor<F,Is...> & jt)177 operator-(typename iterator_adaptor<F, Is...>::difference_type n, 178 const iterator_adaptor<F, Is...> &jt) { 179 return (jt - n); 180 } 181 } 182 } 183 184 #endif 185