1 // Boost.Range library
2 //
3 //  Copyright Neil Groves 2009.
4 //  Copyright Thorsten Ottosen 2003-2004. Use, modification and
5 //  distribution is subject to the Boost Software License, Version
6 //  1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 //  http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // For more information, see http://www.boost.org/libs/range/
10 //
11 
12 #ifndef BOOST_RANGE_SUB_RANGE_HPP
13 #define BOOST_RANGE_SUB_RANGE_HPP
14 
15 #include <boost/detail/workaround.hpp>
16 
17 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
18     #pragma warning( push )
19     #pragma warning( disable : 4996 )
20 #endif
21 
22 #include <boost/range/config.hpp>
23 #include <boost/range/iterator_range.hpp>
24 #include <boost/range/value_type.hpp>
25 #include <boost/range/size_type.hpp>
26 #include <boost/range/difference_type.hpp>
27 #include <boost/range/reference.hpp>
28 #include <boost/range/algorithm/equal.hpp>
29 #include <boost/assert.hpp>
30 #include <boost/type_traits/is_reference.hpp>
31 #include <boost/type_traits/remove_reference.hpp>
32 
33 namespace boost
34 {
35     namespace range_detail
36     {
37 
38 template<class ForwardRange, class TraversalTag>
39 class sub_range_base
40         : public iterator_range<
41             BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
42         >
43 {
44     typedef iterator_range<
45         BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
46     > base;
47 
48 protected:
49     typedef BOOST_DEDUCED_TYPENAME base::iterator_range_ iterator_range_;
50 
51 public:
52     typedef BOOST_DEDUCED_TYPENAME range_value<ForwardRange>::type value_type;
53     typedef BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type iterator;
54     typedef BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type const_iterator;
55     typedef BOOST_DEDUCED_TYPENAME range_difference<ForwardRange>::type difference_type;
56     typedef BOOST_DEDUCED_TYPENAME range_size<ForwardRange>::type size_type;
57     typedef BOOST_DEDUCED_TYPENAME range_reference<ForwardRange>::type reference;
58     typedef BOOST_DEDUCED_TYPENAME range_reference<const ForwardRange>::type const_reference;
59 
sub_range_base()60     sub_range_base()
61     {
62     }
63 
64     template<class Iterator>
sub_range_base(Iterator first,Iterator last)65     sub_range_base(Iterator first, Iterator last)
66         : base(first, last)
67     {
68     }
69 
front()70     reference front()
71     {
72         return base::front();
73     }
74 
front() const75     const_reference front() const
76     {
77         return base::front();
78     }
79 };
80 
81 template<class ForwardRange>
82 class sub_range_base<ForwardRange, bidirectional_traversal_tag>
83         : public sub_range_base<ForwardRange, forward_traversal_tag>
84 {
85     typedef sub_range_base<ForwardRange, forward_traversal_tag> base;
86 public:
sub_range_base()87     sub_range_base()
88     {
89     }
90 
91     template<class Iterator>
sub_range_base(Iterator first,Iterator last)92     sub_range_base(Iterator first, Iterator last)
93         : base(first, last)
94     {
95     }
96 
back()97     BOOST_DEDUCED_TYPENAME base::reference back()
98     {
99         return base::back();
100     }
101 
back() const102     BOOST_DEDUCED_TYPENAME base::const_reference back() const
103     {
104         return base::back();
105     }
106 };
107 
108 template<class ForwardRange>
109 class sub_range_base<ForwardRange, random_access_traversal_tag>
110         : public sub_range_base<ForwardRange, bidirectional_traversal_tag>
111 {
112     typedef sub_range_base<ForwardRange, bidirectional_traversal_tag> base;
113 
114 public:
sub_range_base()115     sub_range_base()
116     {
117     }
118 
119     template<class Iterator>
sub_range_base(Iterator first,Iterator last)120     sub_range_base(Iterator first, Iterator last)
121         : base(first, last)
122     {
123     }
124 
125     BOOST_DEDUCED_TYPENAME base::reference
operator [](BOOST_DEDUCED_TYPENAME base::difference_type n)126     operator[](BOOST_DEDUCED_TYPENAME base::difference_type n)
127     {
128         return this->begin()[n];
129     }
130 
131     BOOST_DEDUCED_TYPENAME base::const_reference
operator [](BOOST_DEDUCED_TYPENAME base::difference_type n) const132     operator[](BOOST_DEDUCED_TYPENAME base::difference_type n) const
133     {
134         return this->begin()[n];
135     }
136 };
137 
138     } // namespace range_detail
139 
140     template<class ForwardRange>
141     class sub_range
142         : public range_detail::sub_range_base<
143                 ForwardRange,
144                 BOOST_DEDUCED_TYPENAME iterator_traversal<
145                     BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
146                 >::type
147             >
148     {
149         typedef BOOST_DEDUCED_TYPENAME range_iterator<
150             ForwardRange
151         >::type iterator_t;
152 
153         typedef range_detail::sub_range_base<
154             ForwardRange,
155             BOOST_DEDUCED_TYPENAME iterator_traversal<
156                 BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type
157             >::type
158         > base;
159 
160         typedef BOOST_DEDUCED_TYPENAME base::impl impl;
161 
162     protected:
163         typedef BOOST_DEDUCED_TYPENAME base::iterator_range_ iterator_range_;
164 
165     private:
166         template<class Source>
167         struct is_compatible_range
168             : is_convertible<
169                 BOOST_DEDUCED_TYPENAME mpl::eval_if<
170                     has_range_iterator<Source>,
171                     range_iterator<Source>,
172                     mpl::identity<void>
173                 >::type,
174                 BOOST_DEDUCED_TYPENAME base::iterator
175             >
176         {
177         };
178 
179     public:
sub_range()180         sub_range()
181         { }
182 
183 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500) )
sub_range(const sub_range & r)184         sub_range(const sub_range& r)
185             : base(impl::adl_begin(const_cast<base&>(static_cast<const base&>(r))),
186                    impl::adl_end(const_cast<base&>(static_cast<const base&>(r))))
187         { }
188 #endif
189 
190         template< class ForwardRange2 >
sub_range(ForwardRange2 & r,BOOST_DEDUCED_TYPENAME::boost::enable_if<is_compatible_range<ForwardRange2>>::type * =0)191         sub_range(
192             ForwardRange2& r,
193             BOOST_DEDUCED_TYPENAME ::boost::enable_if<
194                 is_compatible_range<ForwardRange2>
195             >::type* = 0
196         )
197         : base(impl::adl_begin(r), impl::adl_end(r))
198         {
199         }
200 
201         template< class ForwardRange2 >
sub_range(const ForwardRange2 & r,BOOST_DEDUCED_TYPENAME::boost::enable_if<is_compatible_range<const ForwardRange2>>::type * =0)202         sub_range(
203             const ForwardRange2& r,
204             BOOST_DEDUCED_TYPENAME ::boost::enable_if<
205                 is_compatible_range<const ForwardRange2>
206             >::type* = 0
207         )
208         : base(impl::adl_begin(r), impl::adl_end(r))
209         {
210         }
211 
begin() const212         BOOST_DEDUCED_TYPENAME base::const_iterator begin() const
213         {
214             return base::begin();
215         }
216 
begin()217         BOOST_DEDUCED_TYPENAME base::iterator begin()
218         {
219             return base::begin();
220         }
221 
end() const222         BOOST_DEDUCED_TYPENAME base::const_iterator end() const
223         {
224             return base::end();
225         }
226 
end()227         BOOST_DEDUCED_TYPENAME base::iterator end()
228         {
229             return base::end();
230         }
231 
232         template< class Iter >
sub_range(Iter first,Iter last)233         sub_range( Iter first, Iter last ) :
234             base( first, last )
235         { }
236 
237         template<class ForwardRange2>
238         BOOST_DEDUCED_TYPENAME ::boost::enable_if<
239             is_compatible_range<ForwardRange2>,
240             sub_range&
241         >::type
operator =(ForwardRange2 & r)242         operator=(ForwardRange2& r)
243         {
244             iterator_range_::operator=( r );
245             return *this;
246         }
247 
248         template<class ForwardRange2>
249         BOOST_DEDUCED_TYPENAME ::boost::enable_if<
250             is_compatible_range<const ForwardRange2>,
251             sub_range&
252         >::type
operator =(const ForwardRange2 & r)253         operator=( const ForwardRange2& r )
254         {
255             iterator_range_::operator=( r );
256             return *this;
257         }
258 
operator =(const sub_range & r)259         sub_range& operator=( const sub_range& r )
260         {
261             iterator_range_::operator=( static_cast<const iterator_range_&>(r) );
262             return *this;
263         }
264 
advance_begin(BOOST_DEDUCED_TYPENAME base::difference_type n)265         sub_range& advance_begin(
266             BOOST_DEDUCED_TYPENAME base::difference_type n)
267         {
268             std::advance(this->m_Begin, n);
269             return *this;
270         }
271 
advance_end(BOOST_DEDUCED_TYPENAME base::difference_type n)272         sub_range& advance_end(
273             BOOST_DEDUCED_TYPENAME base::difference_type n)
274         {
275             std::advance(this->m_End, n);
276             return *this;
277         }
278     };
279 
280 } // namespace 'boost'
281 
282 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
283     #pragma warning( pop )
284 #endif
285 
286 #endif
287 
288