range.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // This file was modified by Oracle on 2013-2020.
  4. // Modifications copyright (c) 2013-2020 Oracle and/or its affiliates.
  5. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  6. // Use, modification and distribution is subject to the Boost Software License,
  7. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. #ifndef BOOST_GEOMETRY_UTIL_RANGE_HPP
  10. #define BOOST_GEOMETRY_UTIL_RANGE_HPP
  11. #include <algorithm>
  12. #include <iterator>
  13. #include <type_traits>
  14. #include <boost/concept_check.hpp>
  15. #include <boost/config.hpp>
  16. #include <boost/core/addressof.hpp>
  17. #include <boost/mpl/has_xxx.hpp>
  18. #include <boost/range/concepts.hpp>
  19. #include <boost/range/begin.hpp>
  20. #include <boost/range/end.hpp>
  21. #include <boost/range/empty.hpp>
  22. #include <boost/range/difference_type.hpp>
  23. #include <boost/range/has_range_iterator.hpp>
  24. #include <boost/range/iterator.hpp>
  25. #include <boost/range/rbegin.hpp>
  26. #include <boost/range/reference.hpp>
  27. #include <boost/range/size.hpp>
  28. #include <boost/range/value_type.hpp>
  29. #include <boost/geometry/core/assert.hpp>
  30. #include <boost/geometry/core/mutable_range.hpp>
  31. namespace boost { namespace geometry { namespace range
  32. {
  33. namespace detail
  34. {
  35. BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator_category)
  36. template <typename T>
  37. struct is_iterator
  38. : std::integral_constant
  39. <
  40. bool,
  41. has_iterator_category
  42. <
  43. std::iterator_traits<T>
  44. >::value
  45. >
  46. {};
  47. template <typename T, bool HasIterator = boost::has_range_iterator<T>::value>
  48. struct is_range_impl
  49. : is_iterator
  50. <
  51. typename boost::range_iterator<T>::type
  52. >
  53. {};
  54. template <typename T>
  55. struct is_range_impl<T, false>
  56. : std::false_type
  57. {};
  58. template <typename T>
  59. struct is_range
  60. : is_range_impl<T>
  61. {};
  62. // NOTE: For SinglePassRanges pos could iterate over all elements until the i-th element was met.
  63. template <typename RandomAccessRange>
  64. struct pos
  65. {
  66. typedef typename boost::range_iterator<RandomAccessRange>::type iterator;
  67. typedef typename boost::range_size<RandomAccessRange>::type size_type;
  68. typedef typename boost::range_difference<RandomAccessRange>::type difference_type;
  69. static inline iterator apply(RandomAccessRange & rng, size_type i)
  70. {
  71. BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<RandomAccessRange> ));
  72. return boost::begin(rng) + static_cast<difference_type>(i);
  73. }
  74. };
  75. } // namespace detail
  76. /*!
  77. \brief Short utility to conveniently return an iterator of a RandomAccessRange.
  78. \ingroup utility
  79. */
  80. template <typename RandomAccessRange>
  81. inline typename boost::range_iterator<RandomAccessRange const>::type
  82. pos(RandomAccessRange const& rng,
  83. typename boost::range_size<RandomAccessRange const>::type i)
  84. {
  85. BOOST_GEOMETRY_ASSERT(i <= boost::size(rng));
  86. return detail::pos<RandomAccessRange const>::apply(rng, i);
  87. }
  88. /*!
  89. \brief Short utility to conveniently return an iterator of a RandomAccessRange.
  90. \ingroup utility
  91. */
  92. template <typename RandomAccessRange>
  93. inline typename boost::range_iterator<RandomAccessRange>::type
  94. pos(RandomAccessRange & rng,
  95. typename boost::range_size<RandomAccessRange>::type i)
  96. {
  97. BOOST_GEOMETRY_ASSERT(i <= boost::size(rng));
  98. return detail::pos<RandomAccessRange>::apply(rng, i);
  99. }
  100. /*!
  101. \brief Short utility to conveniently return an element of a RandomAccessRange.
  102. \ingroup utility
  103. */
  104. template <typename RandomAccessRange>
  105. inline typename boost::range_reference<RandomAccessRange const>::type
  106. at(RandomAccessRange const& rng,
  107. typename boost::range_size<RandomAccessRange const>::type i)
  108. {
  109. BOOST_GEOMETRY_ASSERT(i < boost::size(rng));
  110. return * detail::pos<RandomAccessRange const>::apply(rng, i);
  111. }
  112. /*!
  113. \brief Short utility to conveniently return an element of a RandomAccessRange.
  114. \ingroup utility
  115. */
  116. template <typename RandomAccessRange>
  117. inline typename boost::range_reference<RandomAccessRange>::type
  118. at(RandomAccessRange & rng,
  119. typename boost::range_size<RandomAccessRange>::type i)
  120. {
  121. BOOST_GEOMETRY_ASSERT(i < boost::size(rng));
  122. return * detail::pos<RandomAccessRange>::apply(rng, i);
  123. }
  124. /*!
  125. \brief Short utility to conveniently return the front element of a Range.
  126. \ingroup utility
  127. */
  128. template <typename Range>
  129. inline typename boost::range_reference<Range const>::type
  130. front(Range const& rng)
  131. {
  132. BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
  133. return *boost::begin(rng);
  134. }
  135. /*!
  136. \brief Short utility to conveniently return the front element of a Range.
  137. \ingroup utility
  138. */
  139. template <typename Range>
  140. inline typename boost::range_reference<Range>::type
  141. front(Range & rng)
  142. {
  143. BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
  144. return *boost::begin(rng);
  145. }
  146. // NOTE: For SinglePassRanges back() could iterate over all elements until the last element is met.
  147. /*!
  148. \brief Short utility to conveniently return the back element of a BidirectionalRange.
  149. \ingroup utility
  150. */
  151. template <typename BidirectionalRange>
  152. inline typename boost::range_reference<BidirectionalRange const>::type
  153. back(BidirectionalRange const& rng)
  154. {
  155. BOOST_RANGE_CONCEPT_ASSERT(( boost::BidirectionalRangeConcept<BidirectionalRange const> ));
  156. BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
  157. return *(boost::rbegin(rng));
  158. }
  159. /*!
  160. \brief Short utility to conveniently return the back element of a BidirectionalRange.
  161. \ingroup utility
  162. */
  163. template <typename BidirectionalRange>
  164. inline typename boost::range_reference<BidirectionalRange>::type
  165. back(BidirectionalRange & rng)
  166. {
  167. BOOST_RANGE_CONCEPT_ASSERT((boost::BidirectionalRangeConcept<BidirectionalRange>));
  168. BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
  169. return *(boost::rbegin(rng));
  170. }
  171. /*!
  172. \brief Short utility to conveniently clear a mutable range.
  173. It uses traits::clear<>.
  174. \ingroup utility
  175. */
  176. template <typename Range>
  177. inline void clear(Range & rng)
  178. {
  179. // NOTE: this trait is probably not needed since it could be implemented using resize()
  180. geometry::traits::clear<Range>::apply(rng);
  181. }
  182. /*!
  183. \brief Short utility to conveniently insert a new element at the end of a mutable range.
  184. It uses boost::geometry::traits::push_back<>.
  185. \ingroup utility
  186. */
  187. template <typename Range>
  188. inline void push_back(Range & rng,
  189. typename boost::range_value<Range>::type const& value)
  190. {
  191. geometry::traits::push_back<Range>::apply(rng, value);
  192. }
  193. /*!
  194. \brief Short utility to conveniently resize a mutable range.
  195. It uses boost::geometry::traits::resize<>.
  196. \ingroup utility
  197. */
  198. template <typename Range>
  199. inline void resize(Range & rng,
  200. typename boost::range_size<Range>::type new_size)
  201. {
  202. geometry::traits::resize<Range>::apply(rng, new_size);
  203. }
  204. /*!
  205. \brief Short utility to conveniently remove an element from the back of a mutable range.
  206. It uses resize().
  207. \ingroup utility
  208. */
  209. template <typename Range>
  210. inline void pop_back(Range & rng)
  211. {
  212. BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
  213. range::resize(rng, boost::size(rng) - 1);
  214. }
  215. namespace detail {
  216. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  217. template <typename It,
  218. typename OutIt,
  219. bool UseMove = std::is_convertible
  220. <
  221. typename std::iterator_traits<It>::value_type &&,
  222. typename std::iterator_traits<OutIt>::value_type
  223. >::value>
  224. struct copy_or_move_impl
  225. {
  226. static inline OutIt apply(It first, It last, OutIt out)
  227. {
  228. return std::move(first, last, out);
  229. }
  230. };
  231. template <typename It, typename OutIt>
  232. struct copy_or_move_impl<It, OutIt, false>
  233. {
  234. static inline OutIt apply(It first, It last, OutIt out)
  235. {
  236. return std::copy(first, last, out);
  237. }
  238. };
  239. template <typename It, typename OutIt>
  240. inline OutIt copy_or_move(It first, It last, OutIt out)
  241. {
  242. return copy_or_move_impl<It, OutIt>::apply(first, last, out);
  243. }
  244. #else
  245. template <typename It, typename OutIt>
  246. inline OutIt copy_or_move(It first, It last, OutIt out)
  247. {
  248. return std::copy(first, last, out);
  249. }
  250. #endif
  251. } // namespace detail
  252. /*!
  253. \brief Short utility to conveniently remove an element from a mutable range.
  254. It uses std::copy() and resize(). Version taking mutable iterators.
  255. \ingroup utility
  256. */
  257. template <typename Range>
  258. inline typename boost::range_iterator<Range>::type
  259. erase(Range & rng,
  260. typename boost::range_iterator<Range>::type it)
  261. {
  262. BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
  263. BOOST_GEOMETRY_ASSERT(it != boost::end(rng));
  264. typename boost::range_difference<Range>::type const
  265. d = std::distance(boost::begin(rng), it);
  266. typename boost::range_iterator<Range>::type
  267. next = it;
  268. ++next;
  269. detail::copy_or_move(next, boost::end(rng), it);
  270. range::resize(rng, boost::size(rng) - 1);
  271. // NOTE: In general this should be sufficient:
  272. // return it;
  273. // But in MSVC using the returned iterator causes
  274. // assertion failures when iterator debugging is enabled
  275. // Furthermore the code below should work in the case if resize()
  276. // invalidates iterators when the container is resized down.
  277. return boost::begin(rng) + d;
  278. }
  279. /*!
  280. \brief Short utility to conveniently remove an element from a mutable range.
  281. It uses std::copy() and resize(). Version taking non-mutable iterators.
  282. \ingroup utility
  283. */
  284. template <typename Range>
  285. inline typename boost::range_iterator<Range>::type
  286. erase(Range & rng,
  287. typename boost::range_iterator<Range const>::type cit)
  288. {
  289. BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<Range> ));
  290. typename boost::range_iterator<Range>::type
  291. it = boost::begin(rng)
  292. + std::distance(boost::const_begin(rng), cit);
  293. return range::erase(rng, it);
  294. }
  295. /*!
  296. \brief Short utility to conveniently remove a range of elements from a mutable range.
  297. It uses std::copy() and resize(). Version taking mutable iterators.
  298. \ingroup utility
  299. */
  300. template <typename Range>
  301. inline typename boost::range_iterator<Range>::type
  302. erase(Range & rng,
  303. typename boost::range_iterator<Range>::type first,
  304. typename boost::range_iterator<Range>::type last)
  305. {
  306. typename boost::range_difference<Range>::type const
  307. diff = std::distance(first, last);
  308. BOOST_GEOMETRY_ASSERT(diff >= 0);
  309. std::size_t const count = static_cast<std::size_t>(diff);
  310. BOOST_GEOMETRY_ASSERT(count <= boost::size(rng));
  311. if ( count > 0 )
  312. {
  313. typename boost::range_difference<Range>::type const
  314. d = std::distance(boost::begin(rng), first);
  315. detail::copy_or_move(last, boost::end(rng), first);
  316. range::resize(rng, boost::size(rng) - count);
  317. // NOTE: In general this should be sufficient:
  318. // return first;
  319. // But in MSVC using the returned iterator causes
  320. // assertion failures when iterator debugging is enabled
  321. // Furthermore the code below should work in the case if resize()
  322. // invalidates iterators when the container is resized down.
  323. return boost::begin(rng) + d;
  324. }
  325. return first;
  326. }
  327. /*!
  328. \brief Short utility to conveniently remove a range of elements from a mutable range.
  329. It uses std::copy() and resize(). Version taking non-mutable iterators.
  330. \ingroup utility
  331. */
  332. template <typename Range>
  333. inline typename boost::range_iterator<Range>::type
  334. erase(Range & rng,
  335. typename boost::range_iterator<Range const>::type cfirst,
  336. typename boost::range_iterator<Range const>::type clast)
  337. {
  338. BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<Range> ));
  339. typename boost::range_iterator<Range>::type
  340. first = boost::begin(rng)
  341. + std::distance(boost::const_begin(rng), cfirst);
  342. typename boost::range_iterator<Range>::type
  343. last = boost::begin(rng)
  344. + std::distance(boost::const_begin(rng), clast);
  345. return range::erase(rng, first, last);
  346. }
  347. // back_inserter
  348. template <class Container>
  349. class back_insert_iterator
  350. {
  351. public:
  352. typedef std::output_iterator_tag iterator_category;
  353. typedef void value_type;
  354. typedef void difference_type;
  355. typedef void pointer;
  356. typedef void reference;
  357. typedef Container container_type;
  358. explicit back_insert_iterator(Container & c)
  359. : container(boost::addressof(c))
  360. {}
  361. back_insert_iterator & operator=(typename Container::value_type const& value)
  362. {
  363. range::push_back(*container, value);
  364. return *this;
  365. }
  366. back_insert_iterator & operator* ()
  367. {
  368. return *this;
  369. }
  370. back_insert_iterator & operator++ ()
  371. {
  372. return *this;
  373. }
  374. back_insert_iterator operator++(int)
  375. {
  376. return *this;
  377. }
  378. private:
  379. Container * container;
  380. };
  381. template <typename Range>
  382. inline back_insert_iterator<Range> back_inserter(Range & rng)
  383. {
  384. return back_insert_iterator<Range>(rng);
  385. }
  386. }}} // namespace boost::geometry::range
  387. #endif // BOOST_GEOMETRY_UTIL_RANGE_HPP