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