/Src/Dependencies/Boost/boost/range/iterator_range_core.hpp

http://hadesmem.googlecode.com/ · C++ Header · 650 lines · 441 code · 101 blank · 108 comment · 7 complexity · 3c261eadeead03fb7b42e99c02dbf4fd MD5 · raw file

  1. // Boost.Range library
  2. //
  3. // Copyright Neil Groves & Thorsten Ottosen & Pavol Droba 2003-2004.
  4. // Use, modification and distribution is subject to the Boost Software
  5. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // For more information, see http://www.boost.org/libs/range/
  9. //
  10. #ifndef BOOST_RANGE_ITERATOR_RANGE_CORE_HPP_INCLUDED
  11. #define BOOST_RANGE_ITERATOR_RANGE_CORE_HPP_INCLUDED
  12. #include <boost/config.hpp> // Define __STL_CONFIG_H, if appropriate.
  13. #include <boost/detail/workaround.hpp>
  14. #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
  15. #pragma warning( push )
  16. #pragma warning( disable : 4996 )
  17. #endif
  18. #include <boost/assert.hpp>
  19. #include <boost/iterator/iterator_traits.hpp>
  20. #include <boost/iterator/iterator_facade.hpp>
  21. #include <boost/type_traits/is_abstract.hpp>
  22. #include <boost/type_traits/is_pointer.hpp>
  23. #include <boost/range/functions.hpp>
  24. #include <boost/range/iterator.hpp>
  25. #include <boost/range/difference_type.hpp>
  26. #include <boost/range/algorithm/equal.hpp>
  27. #include <boost/range/detail/safe_bool.hpp>
  28. #include <boost/utility/enable_if.hpp>
  29. #include <iterator>
  30. #include <algorithm>
  31. #include <cstddef>
  32. /*! \file
  33. Defines the \c iterator_class and related functions.
  34. \c iterator_range is a simple wrapper of iterator pair idiom. It provides
  35. a rich subset of Container interface.
  36. */
  37. namespace boost
  38. {
  39. namespace iterator_range_detail
  40. {
  41. //
  42. // The functions adl_begin and adl_end are implemented in a separate
  43. // class for gcc-2.9x
  44. //
  45. template<class IteratorT>
  46. struct iterator_range_impl {
  47. template< class ForwardRange >
  48. static IteratorT adl_begin( ForwardRange& r )
  49. {
  50. return static_cast<IteratorT>( boost::begin( r ) );
  51. }
  52. template< class ForwardRange >
  53. static IteratorT adl_end( ForwardRange& r )
  54. {
  55. return static_cast<IteratorT>( boost::end( r ) );
  56. }
  57. };
  58. template< class Left, class Right >
  59. inline bool less_than( const Left& l, const Right& r )
  60. {
  61. return std::lexicographical_compare( boost::begin(l),
  62. boost::end(l),
  63. boost::begin(r),
  64. boost::end(r) );
  65. }
  66. template< class Left, class Right >
  67. inline bool greater_than( const Left& l, const Right& r )
  68. {
  69. return less_than(r,l);
  70. }
  71. template< class Left, class Right >
  72. inline bool less_or_equal_than( const Left& l, const Right& r )
  73. {
  74. return !iterator_range_detail::less_than(r,l);
  75. }
  76. template< class Left, class Right >
  77. inline bool greater_or_equal_than( const Left& l, const Right& r )
  78. {
  79. return !iterator_range_detail::less_than(l,r);
  80. }
  81. // This version is maintained since it is used in other boost libraries
  82. // such as Boost.Assign
  83. template< class Left, class Right >
  84. inline bool equal(const Left& l, const Right& r)
  85. {
  86. return boost::equal(l, r);
  87. }
  88. struct range_tag { };
  89. struct const_range_tag { };
  90. }
  91. // iterator range template class -----------------------------------------//
  92. //! iterator_range class
  93. /*!
  94. An \c iterator_range delimits a range in a sequence by beginning and ending iterators.
  95. An iterator_range can be passed to an algorithm which requires a sequence as an input.
  96. For example, the \c toupper() function may be used most frequently on strings,
  97. but can also be used on iterator_ranges:
  98. \code
  99. boost::tolower( find( s, "UPPERCASE STRING" ) );
  100. \endcode
  101. Many algorithms working with sequences take a pair of iterators,
  102. delimiting a working range, as an arguments. The \c iterator_range class is an
  103. encapsulation of a range identified by a pair of iterators.
  104. It provides a collection interface,
  105. so it is possible to pass an instance to an algorithm requiring a collection as an input.
  106. */
  107. template<class IteratorT>
  108. class iterator_range
  109. {
  110. typedef range_detail::safe_bool< IteratorT iterator_range<IteratorT>::* > safe_bool_t;
  111. protected: // Used by sub_range
  112. //! implementation class
  113. typedef iterator_range_detail::iterator_range_impl<IteratorT> impl;
  114. public:
  115. //! this type
  116. typedef iterator_range<IteratorT> type;
  117. typedef BOOST_DEDUCED_TYPENAME safe_bool_t::unspecified_bool_type unspecified_bool_type;
  118. //BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(value_type);
  119. //! Encapsulated value type
  120. typedef BOOST_DEDUCED_TYPENAME
  121. iterator_value<IteratorT>::type value_type;
  122. //! Difference type
  123. typedef BOOST_DEDUCED_TYPENAME
  124. iterator_difference<IteratorT>::type difference_type;
  125. //! Size type
  126. typedef std::size_t size_type; // note: must be unsigned
  127. //! This type
  128. typedef iterator_range<IteratorT> this_type;
  129. //! Reference type
  130. //
  131. // Needed because value-type is the same for
  132. // const and non-const iterators
  133. //
  134. typedef BOOST_DEDUCED_TYPENAME
  135. iterator_reference<IteratorT>::type reference;
  136. //! const_iterator type
  137. /*!
  138. There is no distinction between const_iterator and iterator.
  139. These typedefs are provides to fulfill container interface
  140. */
  141. typedef IteratorT const_iterator;
  142. //! iterator type
  143. typedef IteratorT iterator;
  144. private: // for return value of operator()()
  145. typedef BOOST_DEDUCED_TYPENAME
  146. boost::mpl::if_< boost::is_abstract<value_type>,
  147. reference, value_type >::type abstract_value_type;
  148. public:
  149. iterator_range() : m_Begin( iterator() ), m_End( iterator() )
  150. { }
  151. //! Constructor from a pair of iterators
  152. template< class Iterator >
  153. iterator_range( Iterator Begin, Iterator End ) :
  154. m_Begin(Begin), m_End(End)
  155. {}
  156. //! Constructor from a Range
  157. template< class Range >
  158. iterator_range( const Range& r ) :
  159. m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
  160. {}
  161. //! Constructor from a Range
  162. template< class Range >
  163. iterator_range( Range& r ) :
  164. m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
  165. {}
  166. //! Constructor from a Range
  167. template< class Range >
  168. iterator_range( const Range& r, iterator_range_detail::const_range_tag ) :
  169. m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
  170. {}
  171. //! Constructor from a Range
  172. template< class Range >
  173. iterator_range( Range& r, iterator_range_detail::range_tag ) :
  174. m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
  175. {}
  176. #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
  177. this_type& operator=( const this_type& r )
  178. {
  179. m_Begin = r.begin();
  180. m_End = r.end();
  181. return *this;
  182. }
  183. #endif
  184. template< class Iterator >
  185. iterator_range& operator=( const iterator_range<Iterator>& r )
  186. {
  187. m_Begin = r.begin();
  188. m_End = r.end();
  189. return *this;
  190. }
  191. template< class ForwardRange >
  192. iterator_range& operator=( ForwardRange& r )
  193. {
  194. m_Begin = impl::adl_begin( r );
  195. m_End = impl::adl_end( r );
  196. return *this;
  197. }
  198. template< class ForwardRange >
  199. iterator_range& operator=( const ForwardRange& r )
  200. {
  201. m_Begin = impl::adl_begin( r );
  202. m_End = impl::adl_end( r );
  203. return *this;
  204. }
  205. IteratorT begin() const
  206. {
  207. return m_Begin;
  208. }
  209. IteratorT end() const
  210. {
  211. return m_End;
  212. }
  213. difference_type size() const
  214. {
  215. return m_End - m_Begin;
  216. }
  217. bool empty() const
  218. {
  219. return m_Begin == m_End;
  220. }
  221. operator unspecified_bool_type() const
  222. {
  223. return safe_bool_t::to_unspecified_bool(m_Begin != m_End, &iterator_range::m_Begin);
  224. }
  225. bool operator!() const
  226. {
  227. return empty();
  228. }
  229. bool equal( const iterator_range& r ) const
  230. {
  231. return m_Begin == r.m_Begin && m_End == r.m_End;
  232. }
  233. #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
  234. bool operator==( const iterator_range& r ) const
  235. {
  236. return boost::equal( *this, r );
  237. }
  238. bool operator!=( const iterator_range& r ) const
  239. {
  240. return !operator==(r);
  241. }
  242. bool operator<( const iterator_range& r ) const
  243. {
  244. return iterator_range_detail::less_than( *this, r );
  245. }
  246. bool operator>( const iterator_range& r ) const
  247. {
  248. return iterator_range_detail::greater_than( *this, r );
  249. }
  250. bool operator<=( const iterator_range& r ) const
  251. {
  252. return iterator_range_detail::less_or_equal_than( *this, r );
  253. }
  254. bool operator>=( const iterator_range& r ) const
  255. {
  256. return iterator_range_detail::greater_or_equal_than( *this, r );
  257. }
  258. #endif
  259. public: // convenience
  260. reference front() const
  261. {
  262. BOOST_ASSERT( !empty() );
  263. return *m_Begin;
  264. }
  265. reference back() const
  266. {
  267. BOOST_ASSERT( !empty() );
  268. IteratorT last( m_End );
  269. return *--last;
  270. }
  271. // pop_front() - added to model the SinglePassRangePrimitiveConcept
  272. void pop_front()
  273. {
  274. BOOST_ASSERT( !empty() );
  275. ++m_Begin;
  276. }
  277. // pop_back() - added to model the BidirectionalRangePrimitiveConcept
  278. void pop_back()
  279. {
  280. BOOST_ASSERT( !empty() );
  281. --m_End;
  282. }
  283. reference operator[]( difference_type at ) const
  284. {
  285. BOOST_ASSERT( at >= 0 && at < size() );
  286. return m_Begin[at];
  287. }
  288. //
  289. // When storing transform iterators, operator[]()
  290. // fails because it returns by reference. Therefore
  291. // operator()() is provided for these cases.
  292. //
  293. abstract_value_type operator()( difference_type at ) const
  294. {
  295. BOOST_ASSERT( at >= 0 && at < size() );
  296. return m_Begin[at];
  297. }
  298. iterator_range& advance_begin( difference_type n )
  299. {
  300. std::advance( m_Begin, n );
  301. return *this;
  302. }
  303. iterator_range& advance_end( difference_type n )
  304. {
  305. std::advance( m_End, n );
  306. return *this;
  307. }
  308. private:
  309. // begin and end iterators
  310. IteratorT m_Begin;
  311. IteratorT m_End;
  312. protected:
  313. //
  314. // Allow subclasses an easy way to access the
  315. // base type
  316. //
  317. typedef iterator_range iterator_range_;
  318. };
  319. // iterator range free-standing operators ---------------------------//
  320. /////////////////////////////////////////////////////////////////////
  321. // comparison operators
  322. /////////////////////////////////////////////////////////////////////
  323. template< class IteratorT, class ForwardRange >
  324. inline bool operator==( const ForwardRange& l,
  325. const iterator_range<IteratorT>& r )
  326. {
  327. return boost::equal( l, r );
  328. }
  329. template< class IteratorT, class ForwardRange >
  330. inline bool operator!=( const ForwardRange& l,
  331. const iterator_range<IteratorT>& r )
  332. {
  333. return !boost::equal( l, r );
  334. }
  335. template< class IteratorT, class ForwardRange >
  336. inline bool operator<( const ForwardRange& l,
  337. const iterator_range<IteratorT>& r )
  338. {
  339. return iterator_range_detail::less_than( l, r );
  340. }
  341. template< class IteratorT, class ForwardRange >
  342. inline bool operator<=( const ForwardRange& l,
  343. const iterator_range<IteratorT>& r )
  344. {
  345. return iterator_range_detail::less_or_equal_than( l, r );
  346. }
  347. template< class IteratorT, class ForwardRange >
  348. inline bool operator>( const ForwardRange& l,
  349. const iterator_range<IteratorT>& r )
  350. {
  351. return iterator_range_detail::greater_than( l, r );
  352. }
  353. template< class IteratorT, class ForwardRange >
  354. inline bool operator>=( const ForwardRange& l,
  355. const iterator_range<IteratorT>& r )
  356. {
  357. return iterator_range_detail::greater_or_equal_than( l, r );
  358. }
  359. #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
  360. #else
  361. template< class Iterator1T, class Iterator2T >
  362. inline bool operator==( const iterator_range<Iterator1T>& l,
  363. const iterator_range<Iterator2T>& r )
  364. {
  365. return boost::equal( l, r );
  366. }
  367. template< class IteratorT, class ForwardRange >
  368. inline bool operator==( const iterator_range<IteratorT>& l,
  369. const ForwardRange& r )
  370. {
  371. return boost::equal( l, r );
  372. }
  373. template< class Iterator1T, class Iterator2T >
  374. inline bool operator!=( const iterator_range<Iterator1T>& l,
  375. const iterator_range<Iterator2T>& r )
  376. {
  377. return !boost::equal( l, r );
  378. }
  379. template< class IteratorT, class ForwardRange >
  380. inline bool operator!=( const iterator_range<IteratorT>& l,
  381. const ForwardRange& r )
  382. {
  383. return !boost::equal( l, r );
  384. }
  385. template< class Iterator1T, class Iterator2T >
  386. inline bool operator<( const iterator_range<Iterator1T>& l,
  387. const iterator_range<Iterator2T>& r )
  388. {
  389. return iterator_range_detail::less_than( l, r );
  390. }
  391. template< class IteratorT, class ForwardRange >
  392. inline bool operator<( const iterator_range<IteratorT>& l,
  393. const ForwardRange& r )
  394. {
  395. return iterator_range_detail::less_than( l, r );
  396. }
  397. template< class Iterator1T, class Iterator2T >
  398. inline bool operator<=( const iterator_range<Iterator1T>& l,
  399. const iterator_range<Iterator2T>& r )
  400. {
  401. return iterator_range_detail::less_or_equal_than( l, r );
  402. }
  403. template< class IteratorT, class ForwardRange >
  404. inline bool operator<=( const iterator_range<IteratorT>& l,
  405. const ForwardRange& r )
  406. {
  407. return iterator_range_detail::less_or_equal_than( l, r );
  408. }
  409. template< class Iterator1T, class Iterator2T >
  410. inline bool operator>( const iterator_range<Iterator1T>& l,
  411. const iterator_range<Iterator2T>& r )
  412. {
  413. return iterator_range_detail::greater_than( l, r );
  414. }
  415. template< class IteratorT, class ForwardRange >
  416. inline bool operator>( const iterator_range<IteratorT>& l,
  417. const ForwardRange& r )
  418. {
  419. return iterator_range_detail::greater_than( l, r );
  420. }
  421. template< class Iterator1T, class Iterator2T >
  422. inline bool operator>=( const iterator_range<Iterator1T>& l,
  423. const iterator_range<Iterator2T>& r )
  424. {
  425. return iterator_range_detail::greater_or_equal_than( l, r );
  426. }
  427. template< class IteratorT, class ForwardRange >
  428. inline bool operator>=( const iterator_range<IteratorT>& l,
  429. const ForwardRange& r )
  430. {
  431. return iterator_range_detail::greater_or_equal_than( l, r );
  432. }
  433. #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
  434. // iterator range utilities -----------------------------------------//
  435. //! iterator_range construct helper
  436. /*!
  437. Construct an \c iterator_range from a pair of iterators
  438. \param Begin A begin iterator
  439. \param End An end iterator
  440. \return iterator_range object
  441. */
  442. template< typename IteratorT >
  443. inline iterator_range< IteratorT >
  444. make_iterator_range( IteratorT Begin, IteratorT End )
  445. {
  446. return iterator_range<IteratorT>( Begin, End );
  447. }
  448. #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
  449. template< typename Range >
  450. inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
  451. make_iterator_range( Range& r )
  452. {
  453. return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
  454. ( boost::begin( r ), boost::end( r ) );
  455. }
  456. #else
  457. //! iterator_range construct helper
  458. /*!
  459. Construct an \c iterator_range from a \c Range containing the begin
  460. and end iterators.
  461. */
  462. template< class ForwardRange >
  463. inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type >
  464. make_iterator_range( ForwardRange& r )
  465. {
  466. return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type >
  467. ( r, iterator_range_detail::range_tag() );
  468. }
  469. template< class ForwardRange >
  470. inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type >
  471. make_iterator_range( const ForwardRange& r )
  472. {
  473. return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type >
  474. ( r, iterator_range_detail::const_range_tag() );
  475. }
  476. #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
  477. namespace iterator_range_detail
  478. {
  479. template< class Range >
  480. inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
  481. make_range_impl( Range& r,
  482. BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
  483. BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
  484. {
  485. //
  486. // Not worth the effort
  487. //
  488. //if( advance_begin == 0 && advance_end == 0 )
  489. // return make_iterator_range( r );
  490. //
  491. BOOST_DEDUCED_TYPENAME range_iterator<Range>::type
  492. new_begin = boost::begin( r ),
  493. new_end = boost::end( r );
  494. std::advance( new_begin, advance_begin );
  495. std::advance( new_end, advance_end );
  496. return make_iterator_range( new_begin, new_end );
  497. }
  498. }
  499. #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
  500. template< class Range >
  501. inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
  502. make_iterator_range( Range& r,
  503. BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
  504. BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
  505. {
  506. //BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" );
  507. return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
  508. }
  509. #else
  510. template< class Range >
  511. inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
  512. make_iterator_range( Range& r,
  513. BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
  514. BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
  515. {
  516. //BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" );
  517. return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
  518. }
  519. template< class Range >
  520. inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const Range>::type >
  521. make_iterator_range( const Range& r,
  522. BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
  523. BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
  524. {
  525. //BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" );
  526. return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
  527. }
  528. #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
  529. //! copy a range into a sequence
  530. /*!
  531. Construct a new sequence of the specified type from the elements
  532. in the given range
  533. \param Range An input range
  534. \return New sequence
  535. */
  536. template< typename SeqT, typename Range >
  537. inline SeqT copy_range( const Range& r )
  538. {
  539. return SeqT( boost::begin( r ), boost::end( r ) );
  540. }
  541. } // namespace 'boost'
  542. #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
  543. #pragma warning( pop )
  544. #endif
  545. #endif