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 32namespace 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 53 iterator_adaptor() { 54 } 55 56 iterator_adaptor(F f, std::tuple<Is...> &&its) : 57 f(f), its(std::move(its)) { 58 } 59 60 reference 61 operator*() const { 62 return tuple::apply(f, tuple::map(derefs(), its)); 63 } 64 65 iterator_adaptor & 66 operator++() { 67 tuple::map(preincs(), its); 68 return *this; 69 } 70 71 iterator_adaptor 72 operator++(int) { 73 auto jt = *this; 74 ++*this; 75 return jt; 76 } 77 78 bool 79 operator==(const iterator_adaptor &jt) const { 80 return its == jt.its; 81 } 82 83 bool 84 operator!=(const iterator_adaptor &jt) const { 85 return its != jt.its; 86 } 87 88 pointer 89 operator->() const { 90 return { **this }; 91 } 92 93 iterator_adaptor & 94 operator--() { 95 tuple::map(predecs(), its); 96 return *this; 97 } 98 99 iterator_adaptor 100 operator--(int) { 101 auto jt = *this; 102 --*this; 103 return jt; 104 } 105 106 iterator_adaptor & 107 operator+=(difference_type n) { 108 tuple::map(advances_by(n), its); 109 return *this; 110 } 111 112 iterator_adaptor & 113 operator-=(difference_type n) { 114 tuple::map(advances_by(-n), its); 115 return *this; 116 } 117 118 iterator_adaptor 119 operator+(difference_type n) const { 120 auto jt = *this; 121 jt += n; 122 return jt; 123 } 124 125 iterator_adaptor 126 operator-(difference_type n) const { 127 auto jt = *this; 128 jt -= n; 129 return jt; 130 } 131 132 difference_type 133 operator-(const iterator_adaptor &jt) const { 134 return std::get<0>(its) - std::get<0>(jt.its); 135 } 136 137 reference 138 operator[](difference_type n) const { 139 return *(*this + n); 140 } 141 142 bool 143 operator<(iterator_adaptor &jt) const { 144 return *this - jt < 0; 145 } 146 147 bool 148 operator>(iterator_adaptor &jt) const { 149 return *this - jt > 0; 150 } 151 152 bool 153 operator>=(iterator_adaptor &jt) const { 154 return !(*this < jt); 155 } 156 157 bool 158 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...> 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...> 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