1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
5 // This file was modified by Oracle on 2013, 2014, 2015, 2016.
6 // Modifications copyright (c) 2013-2016 Oracle and/or its affiliates.
8 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
10 // Use, modification and distribution is subject to the Boost Software License,
11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
12 // http://www.boost.org/LICENSE_1_0.txt)
14 #ifndef BOOST_GEOMETRY_UTIL_RANGE_HPP
15 #define BOOST_GEOMETRY_UTIL_RANGE_HPP
20 #include <boost/concept_check.hpp>
21 #include <boost/config.hpp>
22 #include <boost/core/addressof.hpp>
23 #include <boost/range/concepts.hpp>
24 #include <boost/range/begin.hpp>
25 #include <boost/range/end.hpp>
26 #include <boost/range/empty.hpp>
27 #include <boost/range/difference_type.hpp>
28 #include <boost/range/iterator.hpp>
29 #include <boost/range/rbegin.hpp>
30 #include <boost/range/reference.hpp>
31 #include <boost/range/size.hpp>
32 #include <boost/range/value_type.hpp>
33 #include <boost/type_traits/is_convertible.hpp>
35 #include <boost/geometry/core/assert.hpp>
36 #include <boost/geometry/core/mutable_range.hpp>
38 namespace boost { namespace geometry { namespace range {
42 // NOTE: For SinglePassRanges pos could iterate over all elements until the i-th element was met.
44 template <typename RandomAccessRange>
47 typedef typename boost::range_iterator<RandomAccessRange>::type iterator;
48 typedef typename boost::range_size<RandomAccessRange>::type size_type;
49 typedef typename boost::range_difference<RandomAccessRange>::type difference_type;
51 static inline iterator apply(RandomAccessRange & rng, size_type i)
53 BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<RandomAccessRange> ));
54 return boost::begin(rng) + static_cast<difference_type>(i);
61 \brief Short utility to conveniently return an iterator of a RandomAccessRange.
64 template <typename RandomAccessRange>
65 inline typename boost::range_iterator<RandomAccessRange const>::type
66 pos(RandomAccessRange const& rng,
67 typename boost::range_size<RandomAccessRange const>::type i)
69 BOOST_GEOMETRY_ASSERT(i <= boost::size(rng));
70 return detail::pos<RandomAccessRange const>::apply(rng, i);
74 \brief Short utility to conveniently return an iterator of a RandomAccessRange.
77 template <typename RandomAccessRange>
78 inline typename boost::range_iterator<RandomAccessRange>::type
79 pos(RandomAccessRange & rng,
80 typename boost::range_size<RandomAccessRange>::type i)
82 BOOST_GEOMETRY_ASSERT(i <= boost::size(rng));
83 return detail::pos<RandomAccessRange>::apply(rng, i);
87 \brief Short utility to conveniently return an element of a RandomAccessRange.
90 template <typename RandomAccessRange>
91 inline typename boost::range_reference<RandomAccessRange const>::type
92 at(RandomAccessRange const& rng,
93 typename boost::range_size<RandomAccessRange const>::type i)
95 BOOST_GEOMETRY_ASSERT(i < boost::size(rng));
96 return * detail::pos<RandomAccessRange const>::apply(rng, i);
100 \brief Short utility to conveniently return an element of a RandomAccessRange.
103 template <typename RandomAccessRange>
104 inline typename boost::range_reference<RandomAccessRange>::type
105 at(RandomAccessRange & rng,
106 typename boost::range_size<RandomAccessRange>::type i)
108 BOOST_GEOMETRY_ASSERT(i < boost::size(rng));
109 return * detail::pos<RandomAccessRange>::apply(rng, i);
113 \brief Short utility to conveniently return the front element of a Range.
116 template <typename Range>
117 inline typename boost::range_reference<Range const>::type
118 front(Range const& rng)
120 BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
121 return *boost::begin(rng);
125 \brief Short utility to conveniently return the front element of a Range.
128 template <typename Range>
129 inline typename boost::range_reference<Range>::type
132 BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
133 return *boost::begin(rng);
136 // NOTE: For SinglePassRanges back() could iterate over all elements until the last element is met.
139 \brief Short utility to conveniently return the back element of a BidirectionalRange.
142 template <typename BidirectionalRange>
143 inline typename boost::range_reference<BidirectionalRange const>::type
144 back(BidirectionalRange const& rng)
146 BOOST_RANGE_CONCEPT_ASSERT(( boost::BidirectionalRangeConcept<BidirectionalRange const> ));
147 BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
148 return *(boost::rbegin(rng));
152 \brief Short utility to conveniently return the back element of a BidirectionalRange.
155 template <typename BidirectionalRange>
156 inline typename boost::range_reference<BidirectionalRange>::type
157 back(BidirectionalRange & rng)
159 BOOST_RANGE_CONCEPT_ASSERT((boost::BidirectionalRangeConcept<BidirectionalRange>));
160 BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
161 return *(boost::rbegin(rng));
166 \brief Short utility to conveniently clear a mutable range.
167 It uses traits::clear<>.
170 template <typename Range>
171 inline void clear(Range & rng)
173 // NOTE: this trait is probably not needed since it could be implemented using resize()
174 geometry::traits::clear<Range>::apply(rng);
178 \brief Short utility to conveniently insert a new element at the end of a mutable range.
179 It uses boost::geometry::traits::push_back<>.
182 template <typename Range>
183 inline void push_back(Range & rng,
184 typename boost::range_value<Range>::type const& value)
186 geometry::traits::push_back<Range>::apply(rng, value);
190 \brief Short utility to conveniently resize a mutable range.
191 It uses boost::geometry::traits::resize<>.
194 template <typename Range>
195 inline void resize(Range & rng,
196 typename boost::range_size<Range>::type new_size)
198 geometry::traits::resize<Range>::apply(rng, new_size);
203 \brief Short utility to conveniently remove an element from the back of a mutable range.
207 template <typename Range>
208 inline void pop_back(Range & rng)
210 BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
211 range::resize(rng, boost::size(rng) - 1);
216 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
218 template <typename It,
220 bool UseMove = boost::is_convertible
222 typename std::iterator_traits<It>::value_type &&,
223 typename std::iterator_traits<OutIt>::value_type
225 struct copy_or_move_impl
227 static inline OutIt apply(It first, It last, OutIt out)
229 return std::move(first, last, out);
233 template <typename It, typename OutIt>
234 struct copy_or_move_impl<It, OutIt, false>
236 static inline OutIt apply(It first, It last, OutIt out)
238 return std::copy(first, last, out);
242 template <typename It, typename OutIt>
243 inline OutIt copy_or_move(It first, It last, OutIt out)
245 return copy_or_move_impl<It, OutIt>::apply(first, last, out);
250 template <typename It, typename OutIt>
251 inline OutIt copy_or_move(It first, It last, OutIt out)
253 return std::copy(first, last, out);
258 } // namespace detail
261 \brief Short utility to conveniently remove an element from a mutable range.
262 It uses std::copy() and resize(). Version taking mutable iterators.
265 template <typename Range>
266 inline typename boost::range_iterator<Range>::type
268 typename boost::range_iterator<Range>::type it)
270 BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
271 BOOST_GEOMETRY_ASSERT(it != boost::end(rng));
273 typename boost::range_difference<Range>::type const
274 d = std::distance(boost::begin(rng), it);
276 typename boost::range_iterator<Range>::type
280 detail::copy_or_move(next, boost::end(rng), it);
281 range::resize(rng, boost::size(rng) - 1);
283 // NOTE: In general this should be sufficient:
285 // But in MSVC using the returned iterator causes
286 // assertion failures when iterator debugging is enabled
287 // Furthermore the code below should work in the case if resize()
288 // invalidates iterators when the container is resized down.
289 return boost::begin(rng) + d;
293 \brief Short utility to conveniently remove an element from a mutable range.
294 It uses std::copy() and resize(). Version taking non-mutable iterators.
297 template <typename Range>
298 inline typename boost::range_iterator<Range>::type
300 typename boost::range_iterator<Range const>::type cit)
302 BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<Range> ));
304 typename boost::range_iterator<Range>::type
305 it = boost::begin(rng)
306 + std::distance(boost::const_begin(rng), cit);
308 return erase(rng, it);
312 \brief Short utility to conveniently remove a range of elements from a mutable range.
313 It uses std::copy() and resize(). Version taking mutable iterators.
316 template <typename Range>
317 inline typename boost::range_iterator<Range>::type
319 typename boost::range_iterator<Range>::type first,
320 typename boost::range_iterator<Range>::type last)
322 typename boost::range_difference<Range>::type const
323 diff = std::distance(first, last);
324 BOOST_GEOMETRY_ASSERT(diff >= 0);
326 std::size_t const count = static_cast<std::size_t>(diff);
327 BOOST_GEOMETRY_ASSERT(count <= boost::size(rng));
331 typename boost::range_difference<Range>::type const
332 d = std::distance(boost::begin(rng), first);
334 detail::copy_or_move(last, boost::end(rng), first);
335 range::resize(rng, boost::size(rng) - count);
337 // NOTE: In general this should be sufficient:
339 // But in MSVC using the returned iterator causes
340 // assertion failures when iterator debugging is enabled
341 // Furthermore the code below should work in the case if resize()
342 // invalidates iterators when the container is resized down.
343 return boost::begin(rng) + d;
350 \brief Short utility to conveniently remove a range of elements from a mutable range.
351 It uses std::copy() and resize(). Version taking non-mutable iterators.
354 template <typename Range>
355 inline typename boost::range_iterator<Range>::type
357 typename boost::range_iterator<Range const>::type cfirst,
358 typename boost::range_iterator<Range const>::type clast)
360 BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<Range> ));
362 typename boost::range_iterator<Range>::type
363 first = boost::begin(rng)
364 + std::distance(boost::const_begin(rng), cfirst);
365 typename boost::range_iterator<Range>::type
366 last = boost::begin(rng)
367 + std::distance(boost::const_begin(rng), clast);
369 return erase(rng, first, last);
374 template <class Container>
375 class back_insert_iterator
376 : public std::iterator<std::output_iterator_tag, void, void, void, void>
379 typedef Container container_type;
381 explicit back_insert_iterator(Container & c)
382 : container(boost::addressof(c))
385 back_insert_iterator & operator=(typename Container::value_type const& value)
387 range::push_back(*container, value);
391 back_insert_iterator & operator* ()
396 back_insert_iterator & operator++ ()
401 back_insert_iterator operator++(int)
407 Container * container;
410 template <typename Range>
411 inline back_insert_iterator<Range> back_inserter(Range & rng)
413 return back_insert_iterator<Range>(rng);
416 }}} // namespace boost::geometry::range
418 #endif // BOOST_GEOMETRY_UTIL_RANGE_HPP