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 | // Credits: |
11 | // 'michel' reported Trac 9072 which included a patch for allowing references |
12 | // to function types. |
13 | // |
14 | #ifndef BOOST_RANGE_ITERATOR_RANGE_CORE_HPP_INCLUDED |
15 | #define BOOST_RANGE_ITERATOR_RANGE_CORE_HPP_INCLUDED |
16 | |
17 | #include <boost/config.hpp> // Define __STL_CONFIG_H, if appropriate. |
18 | #include <boost/detail/workaround.hpp> |
19 | |
20 | #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) |
21 | #pragma warning( push ) |
22 | #pragma warning( disable : 4996 ) |
23 | #endif |
24 | |
25 | #include <boost/assert.hpp> |
26 | #include <boost/iterator/iterator_traits.hpp> |
27 | #include <boost/iterator/iterator_facade.hpp> |
28 | #include <boost/mpl/if.hpp> |
29 | #include <boost/mpl/not.hpp> |
30 | #include <boost/mpl/or.hpp> |
31 | #include <boost/type_traits/is_abstract.hpp> |
32 | #include <boost/type_traits/is_array.hpp> |
33 | #include <boost/type_traits/is_base_and_derived.hpp> |
34 | #include <boost/type_traits/is_convertible.hpp> |
35 | #include <boost/type_traits/is_function.hpp> |
36 | #include <boost/type_traits/is_pointer.hpp> |
37 | #include <boost/type_traits/is_same.hpp> |
38 | #include <boost/range/functions.hpp> |
39 | #include <boost/range/iterator.hpp> |
40 | #include <boost/range/difference_type.hpp> |
41 | #include <boost/range/has_range_iterator.hpp> |
42 | #include <boost/range/algorithm/equal.hpp> |
43 | #include <boost/range/detail/safe_bool.hpp> |
44 | #include <boost/utility/enable_if.hpp> |
45 | #include <boost/next_prior.hpp> |
46 | #include <iterator> |
47 | #include <algorithm> |
48 | #include <cstddef> |
49 | |
50 | /*! \file |
51 | Defines the \c iterator_class and related functions. |
52 | \c iterator_range is a simple wrapper of iterator pair idiom. It provides |
53 | a rich subset of Container interface. |
54 | */ |
55 | |
56 | |
57 | namespace boost |
58 | { |
59 | namespace iterator_range_detail |
60 | { |
61 | // |
62 | // The functions adl_begin and adl_end are implemented in a separate |
63 | // class for gcc-2.9x |
64 | // |
65 | template<class IteratorT> |
66 | struct iterator_range_impl { |
67 | template< class ForwardRange > |
68 | static IteratorT adl_begin( ForwardRange& r ) |
69 | { |
70 | return IteratorT( boost::begin( r ) ); |
71 | } |
72 | |
73 | template< class ForwardRange > |
74 | static IteratorT adl_end( ForwardRange& r ) |
75 | { |
76 | return IteratorT( boost::end( r ) ); |
77 | } |
78 | }; |
79 | |
80 | template< class Left, class Right > |
81 | inline bool less_than( const Left& l, const Right& r ) |
82 | { |
83 | return std::lexicographical_compare( boost::begin(l), |
84 | boost::end(l), |
85 | boost::begin(r), |
86 | boost::end(r) ); |
87 | } |
88 | |
89 | template< class Left, class Right > |
90 | inline bool greater_than( const Left& l, const Right& r ) |
91 | { |
92 | return iterator_range_detail::less_than(r,l); |
93 | } |
94 | |
95 | template< class Left, class Right > |
96 | inline bool less_or_equal_than( const Left& l, const Right& r ) |
97 | { |
98 | return !iterator_range_detail::less_than(r,l); |
99 | } |
100 | |
101 | template< class Left, class Right > |
102 | inline bool greater_or_equal_than( const Left& l, const Right& r ) |
103 | { |
104 | return !iterator_range_detail::less_than(l,r); |
105 | } |
106 | |
107 | // This version is maintained since it is used in other boost libraries |
108 | // such as Boost.Assign |
109 | template< class Left, class Right > |
110 | inline bool equal(const Left& l, const Right& r) |
111 | { |
112 | return boost::equal(l, r); |
113 | } |
114 | |
115 | struct range_tag |
116 | { |
117 | }; |
118 | |
119 | struct const_range_tag |
120 | { |
121 | }; |
122 | |
123 | struct iterator_range_tag |
124 | { |
125 | }; |
126 | |
127 | typedef char (&incrementable_t)[1]; |
128 | typedef char (&bidirectional_t)[2]; |
129 | typedef char (&random_access_t)[3]; |
130 | |
131 | incrementable_t test_traversal_tag(boost::incrementable_traversal_tag); |
132 | bidirectional_t test_traversal_tag(boost::bidirectional_traversal_tag); |
133 | random_access_t test_traversal_tag(boost::random_access_traversal_tag); |
134 | |
135 | template<std::size_t S> |
136 | struct pure_iterator_traversal_impl |
137 | { |
138 | typedef boost::incrementable_traversal_tag type; |
139 | }; |
140 | |
141 | template<> |
142 | struct pure_iterator_traversal_impl<sizeof(bidirectional_t)> |
143 | { |
144 | typedef boost::bidirectional_traversal_tag type; |
145 | }; |
146 | |
147 | template<> |
148 | struct pure_iterator_traversal_impl<sizeof(random_access_t)> |
149 | { |
150 | typedef boost::random_access_traversal_tag type; |
151 | }; |
152 | |
153 | template<typename IteratorT> |
154 | struct pure_iterator_traversal |
155 | { |
156 | typedef |
157 | BOOST_DEDUCED_TYPENAME iterator_traversal<IteratorT>::type |
158 | traversal_t; |
159 | BOOST_STATIC_CONSTANT( |
160 | std::size_t, |
161 | traversal_i = sizeof(iterator_range_detail::test_traversal_tag((traversal_t()))) |
162 | ); |
163 | typedef |
164 | BOOST_DEDUCED_TYPENAME pure_iterator_traversal_impl<traversal_i>::type |
165 | type; |
166 | }; |
167 | |
168 | template<class IteratorT, class TraversalTag> |
169 | class iterator_range_base |
170 | : public iterator_range_tag |
171 | { |
172 | typedef range_detail::safe_bool< |
173 | IteratorT iterator_range_base<IteratorT, TraversalTag>::* |
174 | > safe_bool_t; |
175 | |
176 | typedef iterator_range_base<IteratorT, TraversalTag> type; |
177 | |
178 | protected: |
179 | typedef iterator_range_impl<IteratorT> impl; |
180 | |
181 | public: |
182 | typedef BOOST_DEDUCED_TYPENAME |
183 | safe_bool_t::unspecified_bool_type unspecified_bool_type; |
184 | |
185 | typedef BOOST_DEDUCED_TYPENAME |
186 | iterator_value<IteratorT>::type value_type; |
187 | |
188 | typedef BOOST_DEDUCED_TYPENAME |
189 | iterator_difference<IteratorT>::type difference_type; |
190 | |
191 | typedef std::size_t size_type; // note: must be unsigned |
192 | |
193 | // Needed because value-type is the same for |
194 | // const and non-const iterators |
195 | typedef BOOST_DEDUCED_TYPENAME |
196 | iterator_reference<IteratorT>::type reference; |
197 | |
198 | //! const_iterator type |
199 | /*! |
200 | There is no distinction between const_iterator and iterator. |
201 | These typedefs are provides to fulfill container interface |
202 | */ |
203 | typedef IteratorT const_iterator; |
204 | //! iterator type |
205 | typedef IteratorT iterator; |
206 | |
207 | protected: |
208 | iterator_range_base() |
209 | : m_Begin() |
210 | , m_End() |
211 | { |
212 | } |
213 | |
214 | template<class Iterator> |
215 | iterator_range_base(Iterator Begin, Iterator End) |
216 | : m_Begin(Begin) |
217 | , m_End(End) |
218 | { |
219 | } |
220 | |
221 | public: |
222 | IteratorT begin() const |
223 | { |
224 | return m_Begin; |
225 | } |
226 | |
227 | IteratorT end() const |
228 | { |
229 | return m_End; |
230 | } |
231 | |
232 | bool empty() const |
233 | { |
234 | return m_Begin == m_End; |
235 | } |
236 | |
237 | operator unspecified_bool_type() const |
238 | { |
239 | return safe_bool_t::to_unspecified_bool( |
240 | m_Begin != m_End, &iterator_range_base::m_Begin); |
241 | } |
242 | |
243 | bool operator!() const |
244 | { |
245 | return empty(); |
246 | } |
247 | |
248 | bool equal(const iterator_range_base& r) const |
249 | { |
250 | return m_Begin == r.m_Begin && m_End == r.m_End; |
251 | } |
252 | |
253 | reference front() const |
254 | { |
255 | BOOST_ASSERT(!empty()); |
256 | return *m_Begin; |
257 | } |
258 | |
259 | void drop_front() |
260 | { |
261 | BOOST_ASSERT(!empty()); |
262 | ++m_Begin; |
263 | } |
264 | |
265 | void drop_front(difference_type n) |
266 | { |
267 | BOOST_ASSERT(n >= difference_type()); |
268 | std::advance(this->m_Begin, n); |
269 | } |
270 | |
271 | // Deprecated |
272 | void pop_front() { drop_front(); } |
273 | |
274 | protected: |
275 | template<class Iterator> |
276 | void assign(Iterator first, Iterator last) |
277 | { |
278 | m_Begin = first; |
279 | m_End = last; |
280 | } |
281 | |
282 | template<class SinglePassRange> |
283 | void assign(const SinglePassRange& r) |
284 | { |
285 | m_Begin = impl::adl_begin(r); |
286 | m_End = impl::adl_end(r); |
287 | } |
288 | |
289 | template<class SinglePassRange> |
290 | void assign(SinglePassRange& r) |
291 | { |
292 | m_Begin = impl::adl_begin(r); |
293 | m_End = impl::adl_end(r); |
294 | } |
295 | |
296 | IteratorT m_Begin; |
297 | IteratorT m_End; |
298 | }; |
299 | |
300 | template<class IteratorT> |
301 | class iterator_range_base<IteratorT, bidirectional_traversal_tag> |
302 | : public iterator_range_base<IteratorT, incrementable_traversal_tag> |
303 | { |
304 | typedef iterator_range_base<IteratorT, incrementable_traversal_tag> base_type; |
305 | |
306 | protected: |
307 | iterator_range_base() |
308 | { |
309 | } |
310 | |
311 | template<class Iterator> |
312 | iterator_range_base(Iterator first, Iterator last) |
313 | : base_type(first, last) |
314 | { |
315 | } |
316 | |
317 | public: |
318 | typedef BOOST_DEDUCED_TYPENAME base_type::difference_type difference_type; |
319 | typedef BOOST_DEDUCED_TYPENAME base_type::reference reference; |
320 | |
321 | reference back() const |
322 | { |
323 | BOOST_ASSERT(!this->empty()); |
324 | return *boost::prior(this->m_End); |
325 | } |
326 | |
327 | void drop_back() |
328 | { |
329 | BOOST_ASSERT(!this->empty()); |
330 | --this->m_End; |
331 | } |
332 | |
333 | void drop_back(difference_type n) |
334 | { |
335 | BOOST_ASSERT(n >= difference_type()); |
336 | std::advance(this->m_End, -n); |
337 | } |
338 | |
339 | // Deprecated |
340 | void pop_back() { drop_back(); } |
341 | }; |
342 | |
343 | template<class IteratorT> |
344 | class iterator_range_base<IteratorT, random_access_traversal_tag> |
345 | : public iterator_range_base<IteratorT, bidirectional_traversal_tag> |
346 | { |
347 | typedef iterator_range_base< |
348 | IteratorT, bidirectional_traversal_tag> base_type; |
349 | |
350 | public: |
351 | typedef BOOST_DEDUCED_TYPENAME |
352 | boost::mpl::if_< |
353 | boost::mpl::or_< |
354 | boost::is_abstract< |
355 | BOOST_DEDUCED_TYPENAME base_type::value_type |
356 | >, |
357 | boost::is_array< |
358 | BOOST_DEDUCED_TYPENAME base_type::value_type |
359 | >, |
360 | boost::is_function< |
361 | BOOST_DEDUCED_TYPENAME base_type::value_type |
362 | > |
363 | >, |
364 | BOOST_DEDUCED_TYPENAME base_type::reference, |
365 | BOOST_DEDUCED_TYPENAME base_type::value_type |
366 | >::type abstract_value_type; |
367 | |
368 | // Rationale: |
369 | // typedef these here to reduce verbiage in the implementation of this |
370 | // type. |
371 | typedef BOOST_DEDUCED_TYPENAME base_type::difference_type difference_type; |
372 | typedef BOOST_DEDUCED_TYPENAME base_type::size_type size_type; |
373 | typedef BOOST_DEDUCED_TYPENAME base_type::reference reference; |
374 | |
375 | protected: |
376 | iterator_range_base() |
377 | { |
378 | } |
379 | |
380 | template<class Iterator> |
381 | iterator_range_base(Iterator first, Iterator last) |
382 | : base_type(first, last) |
383 | { |
384 | } |
385 | |
386 | public: |
387 | reference operator[](difference_type at) const |
388 | { |
389 | BOOST_ASSERT(at >= 0); |
390 | BOOST_ASSERT(static_cast<typename base_type::size_type>(at) < size()); |
391 | return this->m_Begin[at]; |
392 | } |
393 | |
394 | // |
395 | // When storing transform iterators, operator[]() |
396 | // fails because it returns by reference. Therefore |
397 | // operator()() is provided for these cases. |
398 | // |
399 | abstract_value_type operator()(difference_type at) const |
400 | { |
401 | BOOST_ASSERT(at >= 0); |
402 | BOOST_ASSERT(static_cast<typename base_type::size_type>(at) < size()); |
403 | return this->m_Begin[at]; |
404 | } |
405 | |
406 | BOOST_DEDUCED_TYPENAME base_type::size_type size() const |
407 | { |
408 | return this->m_End - this->m_Begin; |
409 | } |
410 | }; |
411 | |
412 | } |
413 | |
414 | // iterator range template class -----------------------------------------// |
415 | |
416 | //! iterator_range class |
417 | /*! |
418 | An \c iterator_range delimits a range in a sequence by beginning and ending iterators. |
419 | An iterator_range can be passed to an algorithm which requires a sequence as an input. |
420 | For example, the \c toupper() function may be used most frequently on strings, |
421 | but can also be used on iterator_ranges: |
422 | |
423 | \code |
424 | boost::tolower( find( s, "UPPERCASE STRING" ) ); |
425 | \endcode |
426 | |
427 | Many algorithms working with sequences take a pair of iterators, |
428 | delimiting a working range, as an arguments. The \c iterator_range class is an |
429 | encapsulation of a range identified by a pair of iterators. |
430 | It provides a collection interface, |
431 | so it is possible to pass an instance to an algorithm requiring a collection as an input. |
432 | */ |
433 | template<class IteratorT> |
434 | class iterator_range |
435 | : public iterator_range_detail::iterator_range_base< |
436 | IteratorT, |
437 | BOOST_DEDUCED_TYPENAME iterator_range_detail::pure_iterator_traversal<IteratorT>::type |
438 | > |
439 | { |
440 | typedef iterator_range_detail::iterator_range_base< |
441 | IteratorT, |
442 | BOOST_DEDUCED_TYPENAME iterator_range_detail::pure_iterator_traversal<IteratorT>::type |
443 | > base_type; |
444 | |
445 | template<class Source> |
446 | struct is_compatible_range_ |
447 | : is_convertible< |
448 | BOOST_DEDUCED_TYPENAME mpl::eval_if< |
449 | has_range_iterator<Source>, |
450 | range_iterator<Source>, |
451 | mpl::identity<void> |
452 | >::type, |
453 | BOOST_DEDUCED_TYPENAME base_type::iterator |
454 | > |
455 | { |
456 | }; |
457 | |
458 | template<class Source> |
459 | struct is_compatible_range |
460 | : mpl::and_< |
461 | mpl::not_< |
462 | is_convertible< |
463 | Source, |
464 | BOOST_DEDUCED_TYPENAME base_type::iterator |
465 | > |
466 | >, |
467 | is_compatible_range_<Source> |
468 | > |
469 | { |
470 | }; |
471 | |
472 | protected: |
473 | typedef iterator_range_detail::iterator_range_impl<IteratorT> impl; |
474 | |
475 | public: |
476 | typedef iterator_range<IteratorT> type; |
477 | |
478 | iterator_range() |
479 | { |
480 | } |
481 | |
482 | template<class Iterator> |
483 | iterator_range(Iterator first, Iterator last) |
484 | : base_type(first, last) |
485 | { |
486 | } |
487 | |
488 | template<class SinglePassRange> |
489 | iterator_range( |
490 | const SinglePassRange& r, |
491 | BOOST_DEDUCED_TYPENAME ::boost::enable_if< |
492 | is_compatible_range<const SinglePassRange> |
493 | >::type* = 0 |
494 | ) |
495 | : base_type(impl::adl_begin(r), impl::adl_end(r)) |
496 | { |
497 | } |
498 | |
499 | template<class SinglePassRange> |
500 | iterator_range( |
501 | SinglePassRange& r, |
502 | BOOST_DEDUCED_TYPENAME ::boost::enable_if< |
503 | is_compatible_range<SinglePassRange> |
504 | >::type* = 0 |
505 | ) |
506 | : base_type(impl::adl_begin(r), impl::adl_end(r)) |
507 | { |
508 | } |
509 | |
510 | template<class SinglePassRange> |
511 | iterator_range(const SinglePassRange& r, |
512 | iterator_range_detail::const_range_tag) |
513 | : base_type(impl::adl_begin(r), impl::adl_end(r)) |
514 | { |
515 | } |
516 | |
517 | template<class SinglePassRange> |
518 | iterator_range(SinglePassRange& r, |
519 | iterator_range_detail::range_tag) |
520 | : base_type(impl::adl_begin(r), impl::adl_end(r)) |
521 | { |
522 | } |
523 | |
524 | template<class Iterator> |
525 | iterator_range& operator=(const iterator_range<Iterator>& other) |
526 | { |
527 | this->assign(other.begin(), other.end()); |
528 | return *this; |
529 | } |
530 | |
531 | template<class Iterator> |
532 | iterator_range& operator=(iterator_range<Iterator>& other) |
533 | { |
534 | this->assign(other.begin(), other.end()); |
535 | return *this; |
536 | } |
537 | |
538 | template<class SinglePassRange> |
539 | iterator_range& operator=(SinglePassRange& r) |
540 | { |
541 | this->assign(r); |
542 | return *this; |
543 | } |
544 | |
545 | template<class SinglePassRange> |
546 | iterator_range& operator=(const SinglePassRange& r) |
547 | { |
548 | this->assign(r); |
549 | return *this; |
550 | } |
551 | |
552 | iterator_range& advance_begin( |
553 | BOOST_DEDUCED_TYPENAME base_type::difference_type n) |
554 | { |
555 | std::advance(this->m_Begin, n); |
556 | return *this; |
557 | } |
558 | |
559 | iterator_range& advance_end( |
560 | BOOST_DEDUCED_TYPENAME base_type::difference_type n) |
561 | { |
562 | std::advance(this->m_End, n); |
563 | return *this; |
564 | } |
565 | |
566 | protected: |
567 | // |
568 | // Allow subclasses an easy way to access the |
569 | // base type |
570 | // |
571 | typedef iterator_range iterator_range_; |
572 | }; |
573 | |
574 | // iterator range free-standing operators ---------------------------// |
575 | |
576 | ///////////////////////////////////////////////////////////////////// |
577 | // comparison operators |
578 | ///////////////////////////////////////////////////////////////////// |
579 | |
580 | template< class IteratorT, class ForwardRange > |
581 | inline BOOST_DEDUCED_TYPENAME boost::enable_if< |
582 | mpl::not_<is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, |
583 | bool |
584 | >::type |
585 | operator==( const ForwardRange& l, const iterator_range<IteratorT>& r ) |
586 | { |
587 | return boost::equal( l, r ); |
588 | } |
589 | |
590 | template< class IteratorT, class ForwardRange > |
591 | inline BOOST_DEDUCED_TYPENAME boost::enable_if< |
592 | mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, |
593 | bool |
594 | >::type |
595 | operator!=( const ForwardRange& l, const iterator_range<IteratorT>& r ) |
596 | { |
597 | return !boost::equal( l, r ); |
598 | } |
599 | |
600 | template< class IteratorT, class ForwardRange > |
601 | inline BOOST_DEDUCED_TYPENAME boost::enable_if< |
602 | mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, |
603 | bool |
604 | >::type |
605 | operator<( const ForwardRange& l, const iterator_range<IteratorT>& r ) |
606 | { |
607 | return iterator_range_detail::less_than( l, r ); |
608 | } |
609 | |
610 | template< class IteratorT, class ForwardRange > |
611 | inline BOOST_DEDUCED_TYPENAME boost::enable_if< |
612 | mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, |
613 | bool |
614 | >::type |
615 | operator<=( const ForwardRange& l, const iterator_range<IteratorT>& r ) |
616 | { |
617 | return iterator_range_detail::less_or_equal_than( l, r ); |
618 | } |
619 | |
620 | template< class IteratorT, class ForwardRange > |
621 | inline BOOST_DEDUCED_TYPENAME boost::enable_if< |
622 | mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, |
623 | bool |
624 | >::type |
625 | operator>( const ForwardRange& l, const iterator_range<IteratorT>& r ) |
626 | { |
627 | return iterator_range_detail::greater_than( l, r ); |
628 | } |
629 | |
630 | template< class IteratorT, class ForwardRange > |
631 | inline BOOST_DEDUCED_TYPENAME boost::enable_if< |
632 | mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, |
633 | bool |
634 | >::type |
635 | operator>=( const ForwardRange& l, const iterator_range<IteratorT>& r ) |
636 | { |
637 | return iterator_range_detail::greater_or_equal_than( l, r ); |
638 | } |
639 | |
640 | template< class Iterator1T, class Iterator2T > |
641 | inline bool |
642 | operator==( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r ) |
643 | { |
644 | return boost::equal( l, r ); |
645 | } |
646 | |
647 | template< class IteratorT, class ForwardRange > |
648 | inline BOOST_DEDUCED_TYPENAME boost::enable_if< |
649 | mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, |
650 | bool |
651 | >::type |
652 | operator==( const iterator_range<IteratorT>& l, const ForwardRange& r ) |
653 | { |
654 | return boost::equal( l, r ); |
655 | } |
656 | |
657 | |
658 | template< class Iterator1T, class Iterator2T > |
659 | inline bool |
660 | operator!=( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r ) |
661 | { |
662 | return !boost::equal( l, r ); |
663 | } |
664 | |
665 | template< class IteratorT, class ForwardRange > |
666 | inline BOOST_DEDUCED_TYPENAME boost::enable_if< |
667 | mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, |
668 | bool |
669 | >::type |
670 | operator!=( const iterator_range<IteratorT>& l, const ForwardRange& r ) |
671 | { |
672 | return !boost::equal( l, r ); |
673 | } |
674 | |
675 | |
676 | template< class Iterator1T, class Iterator2T > |
677 | inline bool |
678 | operator<( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r ) |
679 | { |
680 | return iterator_range_detail::less_than( l, r ); |
681 | } |
682 | |
683 | template< class IteratorT, class ForwardRange > |
684 | inline BOOST_DEDUCED_TYPENAME boost::enable_if< |
685 | mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, |
686 | bool |
687 | >::type |
688 | operator<( const iterator_range<IteratorT>& l, const ForwardRange& r ) |
689 | { |
690 | return iterator_range_detail::less_than( l, r ); |
691 | } |
692 | |
693 | template< class Iterator1T, class Iterator2T > |
694 | inline bool |
695 | operator<=( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r ) |
696 | { |
697 | return iterator_range_detail::less_or_equal_than( l, r ); |
698 | } |
699 | |
700 | template< class IteratorT, class ForwardRange > |
701 | inline BOOST_DEDUCED_TYPENAME boost::enable_if< |
702 | mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, |
703 | bool |
704 | >::type |
705 | operator<=( const iterator_range<IteratorT>& l, const ForwardRange& r ) |
706 | { |
707 | return iterator_range_detail::less_or_equal_than( l, r ); |
708 | } |
709 | |
710 | template< class Iterator1T, class Iterator2T > |
711 | inline bool |
712 | operator>( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r ) |
713 | { |
714 | return iterator_range_detail::greater_than( l, r ); |
715 | } |
716 | |
717 | template< class IteratorT, class ForwardRange > |
718 | inline BOOST_DEDUCED_TYPENAME boost::enable_if< |
719 | mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, |
720 | bool |
721 | >::type |
722 | operator>( const iterator_range<IteratorT>& l, const ForwardRange& r ) |
723 | { |
724 | return iterator_range_detail::greater_than( l, r ); |
725 | } |
726 | |
727 | template< class Iterator1T, class Iterator2T > |
728 | inline bool |
729 | operator>=( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r ) |
730 | { |
731 | return iterator_range_detail::greater_or_equal_than( l, r ); |
732 | } |
733 | |
734 | template< class IteratorT, class ForwardRange > |
735 | inline BOOST_DEDUCED_TYPENAME boost::enable_if< |
736 | mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, |
737 | bool |
738 | >::type |
739 | operator>=( const iterator_range<IteratorT>& l, const ForwardRange& r ) |
740 | { |
741 | return iterator_range_detail::greater_or_equal_than( l, r ); |
742 | } |
743 | |
744 | // iterator range utilities -----------------------------------------// |
745 | |
746 | //! iterator_range construct helper |
747 | /*! |
748 | Construct an \c iterator_range from a pair of iterators |
749 | |
750 | \param Begin A begin iterator |
751 | \param End An end iterator |
752 | \return iterator_range object |
753 | */ |
754 | template< typename IteratorT > |
755 | inline iterator_range< IteratorT > |
756 | make_iterator_range( IteratorT Begin, IteratorT End ) |
757 | { |
758 | return iterator_range<IteratorT>( Begin, End ); |
759 | } |
760 | |
761 | template<typename IteratorT, typename IntegerT> |
762 | inline iterator_range<IteratorT> |
763 | make_iterator_range_n(IteratorT first, IntegerT n) |
764 | { |
765 | return iterator_range<IteratorT>(first, boost::next(first, n)); |
766 | } |
767 | |
768 | //! iterator_range construct helper |
769 | /*! |
770 | Construct an \c iterator_range from a \c Range containing the begin |
771 | and end iterators. |
772 | */ |
773 | template< class ForwardRange > |
774 | inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type > |
775 | make_iterator_range( ForwardRange& r ) |
776 | { |
777 | return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type > |
778 | ( r, iterator_range_detail::range_tag() ); |
779 | } |
780 | |
781 | template< class ForwardRange > |
782 | inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type > |
783 | make_iterator_range( const ForwardRange& r ) |
784 | { |
785 | return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type > |
786 | ( r, iterator_range_detail::const_range_tag() ); |
787 | } |
788 | |
789 | namespace iterator_range_detail |
790 | { |
791 | template< class Range > |
792 | inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > |
793 | make_range_impl( Range& r, |
794 | BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, |
795 | BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) |
796 | { |
797 | // |
798 | // Not worth the effort |
799 | // |
800 | //if( advance_begin == 0 && advance_end == 0 ) |
801 | // return make_iterator_range( r ); |
802 | // |
803 | |
804 | BOOST_DEDUCED_TYPENAME range_iterator<Range>::type |
805 | new_begin = boost::begin( r ), |
806 | new_end = boost::end( r ); |
807 | std::advance( new_begin, advance_begin ); |
808 | std::advance( new_end, advance_end ); |
809 | return make_iterator_range( new_begin, new_end ); |
810 | } |
811 | } |
812 | |
813 | template< class Range > |
814 | inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > |
815 | make_iterator_range( Range& r, |
816 | BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, |
817 | BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) |
818 | { |
819 | return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); |
820 | } |
821 | |
822 | template< class Range > |
823 | inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const Range>::type > |
824 | make_iterator_range( const Range& r, |
825 | BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, |
826 | BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) |
827 | { |
828 | return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); |
829 | } |
830 | |
831 | //! copy a range into a sequence |
832 | /*! |
833 | Construct a new sequence of the specified type from the elements |
834 | in the given range |
835 | |
836 | \param Range An input range |
837 | \return New sequence |
838 | */ |
839 | template< typename SeqT, typename Range > |
840 | inline SeqT copy_range( const Range& r ) |
841 | { |
842 | return SeqT( boost::begin( r ), boost::end( r ) ); |
843 | } |
844 | |
845 | } // namespace 'boost' |
846 | |
847 | #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) |
848 | #pragma warning( pop ) |
849 | #endif |
850 | |
851 | #endif |
852 | |
853 | |