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 >
adl_beginboost::iterator_range_detail::iterator_range_impl68             static IteratorT adl_begin( ForwardRange& r )
69             {
70                 return IteratorT( boost::begin( r ) );
71             }
72 
73             template< class ForwardRange >
adl_endboost::iterator_range_detail::iterator_range_impl74             static IteratorT adl_end( ForwardRange& r )
75             {
76                 return IteratorT( boost::end( r ) );
77             }
78         };
79 
80         template< class Left, class Right >
less_than(const Left & l,const Right & r)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 >
greater_than(const Left & l,const Right & r)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 >
less_or_equal_than(const Left & l,const Right & r)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 >
greater_or_equal_than(const Left & l,const Right & r)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 >
equal(const Left & l,const Right & r)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:
iterator_range_base()208     iterator_range_base()
209         : m_Begin()
210         , m_End()
211     {
212     }
213 
214     template<class Iterator>
iterator_range_base(Iterator Begin,Iterator End)215     iterator_range_base(Iterator Begin, Iterator End)
216         : m_Begin(Begin)
217         , m_End(End)
218     {
219     }
220 
221 public:
begin() const222     IteratorT begin() const
223     {
224         return m_Begin;
225     }
226 
end() const227     IteratorT end() const
228     {
229         return m_End;
230     }
231 
empty() const232     bool empty() const
233     {
234         return m_Begin == m_End;
235     }
236 
operator unspecified_bool_type() const237     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 
operator !() const243     bool operator!() const
244     {
245         return empty();
246     }
247 
equal(const iterator_range_base & r) const248     bool equal(const iterator_range_base& r) const
249     {
250         return m_Begin == r.m_Begin && m_End == r.m_End;
251     }
252 
front() const253    reference front() const
254    {
255        BOOST_ASSERT(!empty());
256        return *m_Begin;
257    }
258 
drop_front()259    void drop_front()
260    {
261        BOOST_ASSERT(!empty());
262        ++m_Begin;
263    }
264 
drop_front(difference_type n)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
pop_front()272    void pop_front() { drop_front(); }
273 
274 protected:
275     template<class Iterator>
assign(Iterator first,Iterator last)276     void assign(Iterator first, Iterator last)
277     {
278         m_Begin = first;
279         m_End = last;
280     }
281 
282     template<class SinglePassRange>
assign(const SinglePassRange & r)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>
assign(SinglePassRange & r)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:
iterator_range_base()307     iterator_range_base()
308     {
309     }
310 
311     template<class Iterator>
iterator_range_base(Iterator first,Iterator last)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 
back() const321     reference back() const
322     {
323         BOOST_ASSERT(!this->empty());
324         return *boost::prior(this->m_End);
325     }
326 
drop_back()327     void drop_back()
328     {
329         BOOST_ASSERT(!this->empty());
330         --this->m_End;
331     }
332 
drop_back(difference_type n)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
pop_back()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:
iterator_range_base()376     iterator_range_base()
377     {
378     }
379 
380     template<class Iterator>
iterator_range_base(Iterator first,Iterator last)381     iterator_range_base(Iterator first, Iterator last)
382         : base_type(first, last)
383     {
384     }
385 
386 public:
operator [](difference_type at) const387     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     //
operator ()(difference_type at) const399     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 
size() const406     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 
iterator_range()478             iterator_range()
479             {
480             }
481 
482             template<class Iterator>
iterator_range(Iterator first,Iterator last)483             iterator_range(Iterator first, Iterator last)
484                 : base_type(first, last)
485             {
486             }
487 
488             template<class SinglePassRange>
iterator_range(const SinglePassRange & r,BOOST_DEDUCED_TYPENAME::boost::enable_if<is_compatible_range<const SinglePassRange>>::type * =0)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>
iterator_range(SinglePassRange & r,BOOST_DEDUCED_TYPENAME::boost::enable_if<is_compatible_range<SinglePassRange>>::type * =0)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>
iterator_range(const SinglePassRange & r,iterator_range_detail::const_range_tag)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>
iterator_range(SinglePassRange & r,iterator_range_detail::range_tag)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>
operator =(const iterator_range<Iterator> & other)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>
operator =(iterator_range<Iterator> & other)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>
operator =(SinglePassRange & r)539             iterator_range& operator=(SinglePassRange& r)
540             {
541                 this->assign(r);
542                 return *this;
543             }
544 
545             template<class SinglePassRange>
operator =(const SinglePassRange & r)546             iterator_range& operator=(const SinglePassRange& r)
547             {
548                 this->assign(r);
549                 return *this;
550             }
551 
advance_begin(BOOST_DEDUCED_TYPENAME base_type::difference_type n)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 
advance_end(BOOST_DEDUCED_TYPENAME base_type::difference_type n)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
operator ==(const ForwardRange & l,const iterator_range<IteratorT> & r)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
operator !=(const ForwardRange & l,const iterator_range<IteratorT> & r)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
operator <(const ForwardRange & l,const iterator_range<IteratorT> & r)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
operator <=(const ForwardRange & l,const iterator_range<IteratorT> & r)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
operator >(const ForwardRange & l,const iterator_range<IteratorT> & r)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
operator >=(const ForwardRange & l,const iterator_range<IteratorT> & r)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 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
641 #else
642         template< class Iterator1T, class Iterator2T >
643         inline bool
operator ==(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)644         operator==( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r )
645         {
646             return boost::equal( l, r );
647         }
648 
649         template< class IteratorT, class ForwardRange >
650         inline BOOST_DEDUCED_TYPENAME boost::enable_if<
651             mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
652             bool
653         >::type
operator ==(const iterator_range<IteratorT> & l,const ForwardRange & r)654         operator==( const iterator_range<IteratorT>& l, const ForwardRange& r )
655         {
656             return boost::equal( l, r );
657         }
658 
659 
660         template< class Iterator1T, class Iterator2T >
661         inline bool
operator !=(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)662         operator!=( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r )
663         {
664             return !boost::equal( l, r );
665         }
666 
667         template< class IteratorT, class ForwardRange >
668         inline BOOST_DEDUCED_TYPENAME boost::enable_if<
669             mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
670             bool
671         >::type
operator !=(const iterator_range<IteratorT> & l,const ForwardRange & r)672         operator!=( const iterator_range<IteratorT>& l, const ForwardRange& r )
673         {
674             return !boost::equal( l, r );
675         }
676 
677 
678         template< class Iterator1T, class Iterator2T >
679         inline bool
operator <(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)680         operator<( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r )
681         {
682             return iterator_range_detail::less_than( l, r );
683         }
684 
685         template< class IteratorT, class ForwardRange >
686         inline BOOST_DEDUCED_TYPENAME boost::enable_if<
687             mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
688             bool
689         >::type
operator <(const iterator_range<IteratorT> & l,const ForwardRange & r)690         operator<( const iterator_range<IteratorT>& l, const ForwardRange& r )
691         {
692             return iterator_range_detail::less_than( l, r );
693         }
694 
695         template< class Iterator1T, class Iterator2T >
696         inline bool
operator <=(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)697         operator<=( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r )
698         {
699             return iterator_range_detail::less_or_equal_than( l, r );
700         }
701 
702         template< class IteratorT, class ForwardRange >
703         inline BOOST_DEDUCED_TYPENAME boost::enable_if<
704             mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
705             bool
706         >::type
operator <=(const iterator_range<IteratorT> & l,const ForwardRange & r)707         operator<=( const iterator_range<IteratorT>& l, const ForwardRange& r )
708         {
709             return iterator_range_detail::less_or_equal_than( l, r );
710         }
711 
712         template< class Iterator1T, class Iterator2T >
713         inline bool
operator >(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)714         operator>( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r )
715         {
716             return iterator_range_detail::greater_than( l, r );
717         }
718 
719         template< class IteratorT, class ForwardRange >
720         inline BOOST_DEDUCED_TYPENAME boost::enable_if<
721             mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
722             bool
723         >::type
operator >(const iterator_range<IteratorT> & l,const ForwardRange & r)724         operator>( const iterator_range<IteratorT>& l, const ForwardRange& r )
725         {
726             return iterator_range_detail::greater_than( l, r );
727         }
728 
729         template< class Iterator1T, class Iterator2T >
730         inline bool
operator >=(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)731         operator>=( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r )
732         {
733             return iterator_range_detail::greater_or_equal_than( l, r );
734         }
735 
736         template< class IteratorT, class ForwardRange >
737         inline BOOST_DEDUCED_TYPENAME boost::enable_if<
738             mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >,
739             bool
740         >::type
operator >=(const iterator_range<IteratorT> & l,const ForwardRange & r)741         operator>=( const iterator_range<IteratorT>& l, const ForwardRange& r )
742         {
743             return iterator_range_detail::greater_or_equal_than( l, r );
744         }
745 
746 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
747 
748 //  iterator range utilities -----------------------------------------//
749 
750         //! iterator_range construct helper
751         /*!
752             Construct an \c iterator_range from a pair of iterators
753 
754             \param Begin A begin iterator
755             \param End An end iterator
756             \return iterator_range object
757         */
758         template< typename IteratorT >
759         inline iterator_range< IteratorT >
make_iterator_range(IteratorT Begin,IteratorT End)760         make_iterator_range( IteratorT Begin, IteratorT End )
761         {
762             return iterator_range<IteratorT>( Begin, End );
763         }
764 
765         template<typename IteratorT, typename IntegerT>
766         inline iterator_range<IteratorT>
make_iterator_range_n(IteratorT first,IntegerT n)767         make_iterator_range_n(IteratorT first, IntegerT n)
768         {
769             return iterator_range<IteratorT>(first, boost::next(first, n));
770         }
771 
772 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
773 
774         template< typename Range >
775         inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
make_iterator_range(Range & r)776         make_iterator_range( Range& r )
777         {
778             return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
779                 ( boost::begin( r ), boost::end( r ) );
780         }
781 
782 #else
783         //! iterator_range construct helper
784         /*!
785             Construct an \c iterator_range from a \c Range containing the begin
786             and end iterators.
787         */
788         template< class ForwardRange >
789         inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type >
make_iterator_range(ForwardRange & r)790         make_iterator_range( ForwardRange& r )
791         {
792            return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type >
793                 ( r, iterator_range_detail::range_tag() );
794         }
795 
796         template< class ForwardRange >
797         inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type >
make_iterator_range(const ForwardRange & r)798         make_iterator_range( const ForwardRange& r )
799         {
800            return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type >
801                 ( r, iterator_range_detail::const_range_tag() );
802         }
803 
804 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
805 
806         namespace iterator_range_detail
807         {
808             template< class Range >
809             inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
make_range_impl(Range & r,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end)810             make_range_impl( Range& r,
811                              BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
812                              BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
813             {
814                 //
815                 // Not worth the effort
816                 //
817                 //if( advance_begin == 0 && advance_end == 0 )
818                 //    return make_iterator_range( r );
819                 //
820 
821                 BOOST_DEDUCED_TYPENAME range_iterator<Range>::type
822                     new_begin = boost::begin( r ),
823                     new_end   = boost::end( r );
824                 std::advance( new_begin, advance_begin );
825                 std::advance( new_end, advance_end );
826                 return make_iterator_range( new_begin, new_end );
827             }
828         }
829 
830 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
831 
832         template< class Range >
833         inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
make_iterator_range(Range & r,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end)834         make_iterator_range( Range& r,
835                     BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
836                     BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
837         {
838             return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
839         }
840 
841 #else
842 
843         template< class Range >
844         inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
make_iterator_range(Range & r,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end)845         make_iterator_range( Range& r,
846                     BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
847                     BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
848         {
849             return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
850         }
851 
852         template< class Range >
853         inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const Range>::type >
make_iterator_range(const Range & r,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end)854         make_iterator_range( const Range& r,
855                     BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
856                     BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
857         {
858             return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
859         }
860 
861 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
862 
863         //! copy a range into a sequence
864         /*!
865             Construct a new sequence of the specified type from the elements
866             in the given range
867 
868             \param Range An input range
869             \return New sequence
870         */
871         template< typename SeqT, typename Range >
copy_range(const Range & r)872         inline SeqT copy_range( const Range& r )
873         {
874             return SeqT( boost::begin( r ), boost::end( r ) );
875         }
876 
877 } // namespace 'boost'
878 
879 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
880     #pragma warning( pop )
881 #endif
882 
883 #endif
884 
885