annotate DEPENDENCIES/generic/include/boost/range/adaptor/indexed.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@101 1 // Copyright 2014 Neil Groves
Chris@16 2 //
Chris@101 3 // Copyright (c) 2010 Ilya Murav'jov
Chris@101 4 //
Chris@101 5 // Use, modification and distribution is subject to the Boost Software License,
Chris@101 6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 7 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 8 //
Chris@101 9 // Credits:
Chris@101 10 // My (Neil's) first indexed adaptor was hindered by having the underlying
Chris@101 11 // iterator return the same reference as the wrapped iterator. This meant that
Chris@101 12 // to obtain the index one had to get to the index_iterator and call the
Chris@101 13 // index() function on it. Ilya politely pointed out that this was useless in
Chris@101 14 // a number of scenarios since one naturally hides the use of iterators in
Chris@101 15 // good range-based code. Ilya provided a new interface (which has remained)
Chris@101 16 // and a first implementation. Much of this original implementation has
Chris@101 17 // been simplified and now supports more compilers and platforms.
Chris@16 18 //
Chris@101 19 #ifndef BOOST_RANGE_ADAPTOR_INDEXED_HPP_INCLUDED
Chris@101 20 #define BOOST_RANGE_ADAPTOR_INDEXED_HPP_INCLUDED
Chris@16 21
Chris@101 22 #include <boost/range/config.hpp>
Chris@16 23 #include <boost/range/adaptor/argument_fwd.hpp>
Chris@16 24 #include <boost/range/iterator_range.hpp>
Chris@101 25 #include <boost/range/traversal.hpp>
Chris@101 26 #include <boost/range/size.hpp>
Chris@16 27 #include <boost/range/begin.hpp>
Chris@16 28 #include <boost/range/end.hpp>
Chris@101 29 #include <boost/mpl/if.hpp>
Chris@101 30 #include <boost/type_traits/is_convertible.hpp>
Chris@16 31
Chris@101 32 #include <boost/iterator/iterator_traits.hpp>
Chris@101 33 #include <boost/iterator/iterator_facade.hpp>
Chris@16 34
Chris@101 35 #include <boost/tuple/tuple.hpp>
Chris@16 36
Chris@16 37 namespace boost
Chris@16 38 {
Chris@16 39 namespace adaptors
Chris@16 40 {
Chris@101 41
Chris@101 42 struct indexed
Chris@101 43 {
Chris@101 44 explicit indexed(std::ptrdiff_t x = 0)
Chris@101 45 : val(x)
Chris@101 46 {
Chris@101 47 }
Chris@101 48 std::ptrdiff_t val;
Chris@101 49 };
Chris@101 50
Chris@101 51 } // namespace adaptors
Chris@101 52
Chris@101 53 namespace range
Chris@101 54 {
Chris@101 55
Chris@101 56 // Why yet another "pair" class:
Chris@101 57 // - std::pair can't store references
Chris@101 58 // - no need for typing for index type (default to "std::ptrdiff_t"); this is
Chris@101 59 // useful in BOOST_FOREACH() expressions that have pitfalls with commas
Chris@101 60 // ( see http://www.boost.org/doc/libs/1_44_0/doc/html/foreach/pitfalls.html )
Chris@101 61 // - meaningful access functions index(), value()
Chris@101 62 template<class T, class Indexable = std::ptrdiff_t>
Chris@101 63 class index_value
Chris@101 64 : public tuple<Indexable, T>
Chris@101 65 {
Chris@101 66 typedef tuple<Indexable, T> base_t;
Chris@101 67
Chris@101 68 template<int N>
Chris@101 69 struct iv_types
Chris@101 70 {
Chris@101 71 typedef typename tuples::element<N, base_t>::type n_type;
Chris@101 72
Chris@101 73 typedef typename tuples::access_traits<n_type>::non_const_type non_const_type;
Chris@101 74 typedef typename tuples::access_traits<n_type>::const_type const_type;
Chris@101 75 };
Chris@101 76
Chris@101 77 public:
Chris@101 78 typedef typename iv_types<0>::non_const_type index_type;
Chris@101 79 typedef typename iv_types<0>::const_type const_index_type;
Chris@101 80 typedef typename iv_types<1>::non_const_type value_type;
Chris@101 81 typedef typename iv_types<1>::const_type const_value_type;
Chris@101 82
Chris@101 83 index_value()
Chris@101 84 {
Chris@16 85 }
Chris@16 86
Chris@101 87 index_value(typename tuples::access_traits<Indexable>::parameter_type t0,
Chris@101 88 typename tuples::access_traits<T>::parameter_type t1)
Chris@101 89 : base_t(t0, t1)
Chris@16 90 {
Chris@101 91 }
Chris@16 92
Chris@101 93 // member functions index(), value() (non-const and const)
Chris@101 94 index_type index()
Chris@101 95 {
Chris@101 96 return boost::tuples::get<0>(*this);
Chris@101 97 }
Chris@16 98
Chris@101 99 const_index_type index() const
Chris@101 100 {
Chris@101 101 return boost::tuples::get<0>(*this);
Chris@101 102 }
Chris@16 103
Chris@101 104 value_type value()
Chris@101 105 {
Chris@101 106 return boost::tuples::get<1>(*this);
Chris@101 107 }
Chris@16 108
Chris@101 109 const_value_type value() const
Chris@101 110 {
Chris@101 111 return boost::tuples::get<1>(*this);
Chris@101 112 }
Chris@101 113 };
Chris@16 114
Chris@101 115 } // namespace range
Chris@16 116
Chris@101 117 namespace range_detail
Chris@101 118 {
Chris@16 119
Chris@101 120 template<typename Iter>
Chris@101 121 struct indexed_iterator_value_type
Chris@101 122 {
Chris@101 123 typedef ::boost::range::index_value<
Chris@101 124 typename iterator_reference<Iter>::type,
Chris@101 125 typename iterator_difference<Iter>::type
Chris@101 126 > type;
Chris@101 127 };
Chris@16 128
Chris@101 129 // Meta-function to get the traversal for the range and therefore iterator
Chris@101 130 // returned by the indexed adaptor for a specified iterator type.
Chris@101 131 //
Chris@101 132 // Random access -> Random access
Chris@101 133 // Bidirectional -> Forward
Chris@101 134 // Forward -> Forward
Chris@101 135 // SinglePass -> SinglePass
Chris@101 136 //
Chris@101 137 // The rationale for demoting a Bidirectional input to Forward is that the end
Chris@101 138 // iterator cannot cheaply have an index computed for it. Therefore I chose to
Chris@101 139 // demote to forward traversal. I can maintain the ability to traverse randomly
Chris@101 140 // when the input is Random Access since the index for the end iterator is cheap
Chris@101 141 // to compute.
Chris@101 142 template<typename Iter>
Chris@101 143 struct indexed_traversal
Chris@101 144 {
Chris@101 145 private:
Chris@101 146 typedef typename iterator_traversal<Iter>::type wrapped_traversal;
Chris@16 147
Chris@101 148 public:
Chris@16 149
Chris@101 150 typedef typename mpl::if_<
Chris@101 151 is_convertible<wrapped_traversal, random_access_traversal_tag>,
Chris@101 152 random_access_traversal_tag,
Chris@101 153 typename mpl::if_<
Chris@101 154 is_convertible<wrapped_traversal, bidirectional_traversal_tag>,
Chris@101 155 forward_traversal_tag,
Chris@101 156 wrapped_traversal
Chris@101 157 >::type
Chris@101 158 >::type type;
Chris@101 159 };
Chris@16 160
Chris@101 161 template<typename Iter>
Chris@101 162 class indexed_iterator
Chris@101 163 : public iterator_facade<
Chris@101 164 indexed_iterator<Iter>,
Chris@101 165 typename indexed_iterator_value_type<Iter>::type,
Chris@101 166 typename indexed_traversal<Iter>::type,
Chris@101 167 typename indexed_iterator_value_type<Iter>::type,
Chris@101 168 typename iterator_difference<Iter>::type
Chris@101 169 >
Chris@101 170 {
Chris@101 171 public:
Chris@101 172 typedef Iter wrapped;
Chris@16 173
Chris@101 174 private:
Chris@101 175 typedef iterator_facade<
Chris@101 176 indexed_iterator<wrapped>,
Chris@101 177 typename indexed_iterator_value_type<wrapped>::type,
Chris@101 178 typename indexed_traversal<wrapped>::type,
Chris@101 179 typename indexed_iterator_value_type<wrapped>::type,
Chris@101 180 typename iterator_difference<wrapped>::type
Chris@101 181 > base_t;
Chris@101 182
Chris@101 183 public:
Chris@101 184 typedef typename base_t::difference_type difference_type;
Chris@101 185 typedef typename base_t::reference reference;
Chris@101 186 typedef typename base_t::difference_type index_type;
Chris@101 187
Chris@101 188 indexed_iterator()
Chris@101 189 : m_it()
Chris@101 190 , m_index()
Chris@101 191 {
Chris@101 192 }
Chris@101 193
Chris@101 194 template<typename OtherWrapped>
Chris@101 195 indexed_iterator(
Chris@101 196 const indexed_iterator<OtherWrapped>& other,
Chris@101 197 typename enable_if<is_convertible<OtherWrapped, wrapped> >::type* = 0
Chris@101 198 )
Chris@101 199 : m_it(other.get())
Chris@101 200 , m_index(other.get_index())
Chris@101 201 {
Chris@101 202 }
Chris@101 203
Chris@101 204 explicit indexed_iterator(wrapped it, index_type index)
Chris@101 205 : m_it(it)
Chris@101 206 , m_index(index)
Chris@101 207 {
Chris@101 208 }
Chris@101 209
Chris@101 210 wrapped get() const
Chris@101 211 {
Chris@101 212 return m_it;
Chris@101 213 }
Chris@101 214
Chris@101 215 index_type get_index() const
Chris@101 216 {
Chris@101 217 return m_index;
Chris@101 218 }
Chris@101 219
Chris@101 220 private:
Chris@101 221 friend class boost::iterator_core_access;
Chris@101 222
Chris@101 223 reference dereference() const
Chris@101 224 {
Chris@101 225 return reference(m_index, *m_it);
Chris@101 226 }
Chris@101 227
Chris@101 228 bool equal(const indexed_iterator& other) const
Chris@101 229 {
Chris@101 230 return m_it == other.m_it;
Chris@101 231 }
Chris@101 232
Chris@101 233 void increment()
Chris@101 234 {
Chris@101 235 ++m_index;
Chris@101 236 ++m_it;
Chris@101 237 }
Chris@101 238
Chris@101 239 void decrement()
Chris@101 240 {
Chris@101 241 BOOST_ASSERT_MSG(m_index > 0, "indexed Iterator out of bounds");
Chris@101 242 --m_index;
Chris@101 243 --m_it;
Chris@101 244 }
Chris@101 245
Chris@101 246 void advance(index_type n)
Chris@101 247 {
Chris@101 248 m_index += n;
Chris@101 249 BOOST_ASSERT_MSG(m_index >= 0, "indexed Iterator out of bounds");
Chris@101 250 m_it += n;
Chris@101 251 }
Chris@101 252
Chris@101 253 difference_type distance_to(const indexed_iterator& other) const
Chris@101 254 {
Chris@101 255 return other.m_it - m_it;
Chris@101 256 }
Chris@101 257
Chris@101 258 wrapped m_it;
Chris@101 259 index_type m_index;
Chris@101 260 };
Chris@101 261
Chris@101 262 template<typename SinglePassRange>
Chris@101 263 struct indexed_range
Chris@101 264 : iterator_range<
Chris@101 265 indexed_iterator<
Chris@101 266 typename range_iterator<SinglePassRange>::type
Chris@101 267 >
Chris@101 268 >
Chris@101 269 {
Chris@101 270 typedef iterator_range<
Chris@101 271 indexed_iterator<
Chris@101 272 typename range_iterator<SinglePassRange>::type
Chris@101 273 >
Chris@101 274 > base_t;
Chris@101 275
Chris@101 276 BOOST_RANGE_CONCEPT_ASSERT((
Chris@101 277 boost::SinglePassRangeConcept<SinglePassRange>));
Chris@101 278 public:
Chris@101 279 typedef indexed_iterator<
Chris@101 280 typename range_iterator<SinglePassRange>::type
Chris@101 281 > iterator;
Chris@101 282
Chris@101 283 // Constructor for non-random access iterators.
Chris@101 284 // This sets the end iterator index to i despite this being incorrect it
Chris@101 285 // is never observable since bidirectional iterators are demoted to
Chris@101 286 // forward iterators.
Chris@101 287 indexed_range(
Chris@101 288 typename base_t::difference_type i,
Chris@101 289 SinglePassRange& r,
Chris@101 290 single_pass_traversal_tag
Chris@101 291 )
Chris@101 292 : base_t(iterator(boost::begin(r), i),
Chris@101 293 iterator(boost::end(r), i))
Chris@101 294 {
Chris@101 295 }
Chris@101 296
Chris@101 297 indexed_range(
Chris@101 298 typename base_t::difference_type i,
Chris@101 299 SinglePassRange& r,
Chris@101 300 random_access_traversal_tag
Chris@101 301 )
Chris@101 302 : base_t(iterator(boost::begin(r), i),
Chris@101 303 iterator(boost::end(r), i + boost::size(r)))
Chris@101 304 {
Chris@101 305 }
Chris@101 306 };
Chris@101 307
Chris@101 308 } // namespace range_detail
Chris@101 309
Chris@16 310 using range_detail::indexed_range;
Chris@16 311
Chris@16 312 namespace adaptors
Chris@16 313 {
Chris@16 314
Chris@101 315 template<class SinglePassRange>
Chris@101 316 inline indexed_range<SinglePassRange>
Chris@101 317 operator|(SinglePassRange& r, indexed e)
Chris@101 318 {
Chris@101 319 BOOST_RANGE_CONCEPT_ASSERT((
Chris@101 320 boost::SinglePassRangeConcept<SinglePassRange>
Chris@101 321 ));
Chris@101 322 return indexed_range<SinglePassRange>(
Chris@101 323 e.val, r,
Chris@101 324 typename range_traversal<SinglePassRange>::type());
Chris@16 325 }
Chris@16 326
Chris@101 327 template<class SinglePassRange>
Chris@101 328 inline indexed_range<const SinglePassRange>
Chris@101 329 operator|(const SinglePassRange& r, indexed e)
Chris@101 330 {
Chris@101 331 BOOST_RANGE_CONCEPT_ASSERT((
Chris@101 332 boost::SinglePassRangeConcept<const SinglePassRange>
Chris@101 333 ));
Chris@101 334 return indexed_range<const SinglePassRange>(
Chris@101 335 e.val, r,
Chris@101 336 typename range_traversal<const SinglePassRange>::type());
Chris@101 337 }
Chris@16 338
Chris@101 339 template<class SinglePassRange>
Chris@101 340 inline indexed_range<SinglePassRange>
Chris@101 341 index(
Chris@101 342 SinglePassRange& rng,
Chris@101 343 typename range_difference<SinglePassRange>::type index_value = 0)
Chris@101 344 {
Chris@101 345 BOOST_RANGE_CONCEPT_ASSERT((
Chris@101 346 boost::SinglePassRangeConcept<SinglePassRange>
Chris@101 347 ));
Chris@101 348 return indexed_range<SinglePassRange>(
Chris@101 349 index_value, rng,
Chris@101 350 typename range_traversal<SinglePassRange>::type());
Chris@101 351 }
Chris@101 352
Chris@101 353 template<class SinglePassRange>
Chris@101 354 inline indexed_range<const SinglePassRange>
Chris@101 355 index(
Chris@101 356 const SinglePassRange& rng,
Chris@101 357 typename range_difference<const SinglePassRange>::type index_value = 0)
Chris@101 358 {
Chris@101 359 BOOST_RANGE_CONCEPT_ASSERT((
Chris@101 360 boost::SinglePassRangeConcept<SinglePassRange>
Chris@101 361 ));
Chris@101 362 return indexed_range<const SinglePassRange>(
Chris@101 363 index_value, rng,
Chris@101 364 typename range_traversal<const SinglePassRange>::type());
Chris@101 365 }
Chris@101 366
Chris@101 367 } // namespace adaptors
Chris@101 368 } // namespace boost
Chris@101 369
Chris@101 370 #endif // include guard