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
33namespace boost
34{
35 namespace range_detail
36 {
37
38template<class ForwardRange, class TraversalTag>
39class 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
48protected:
49 typedef BOOST_DEDUCED_TYPENAME base::iterator_range_ iterator_range_;
50
51public:
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
60 sub_range_base()
61 {
62 }
63
64 template<class Iterator>
65 sub_range_base(Iterator first, Iterator last)
66 : base(first, last)
67 {
68 }
69
70 reference front()
71 {
72 return base::front();
73 }
74
75 const_reference front() const
76 {
77 return base::front();
78 }
79};
80
81template<class ForwardRange>
82class 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;
86public:
87 sub_range_base()
88 {
89 }
90
91 template<class Iterator>
92 sub_range_base(Iterator first, Iterator last)
93 : base(first, last)
94 {
95 }
96
97 BOOST_DEDUCED_TYPENAME base::reference back()
98 {
99 return base::back();
100 }
101
102 BOOST_DEDUCED_TYPENAME base::const_reference back() const
103 {
104 return base::back();
105 }
106};
107
108template<class ForwardRange>
109class 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
114public:
115 sub_range_base()
116 {
117 }
118
119 template<class Iterator>
120 sub_range_base(Iterator first, Iterator last)
121 : base(first, last)
122 {
123 }
124
125 BOOST_DEDUCED_TYPENAME base::reference
126 operator[](BOOST_DEDUCED_TYPENAME base::difference_type n)
127 {
128 return this->begin()[n];
129 }
130
131 BOOST_DEDUCED_TYPENAME base::const_reference
132 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:
180 sub_range()
181 { }
182
183#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500) )
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 >
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 >
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
212 BOOST_DEDUCED_TYPENAME base::const_iterator begin() const
213 {
214 return base::begin();
215 }
216
217 BOOST_DEDUCED_TYPENAME base::iterator begin()
218 {
219 return base::begin();
220 }
221
222 BOOST_DEDUCED_TYPENAME base::const_iterator end() const
223 {
224 return base::end();
225 }
226
227 BOOST_DEDUCED_TYPENAME base::iterator end()
228 {
229 return base::end();
230 }
231
232 template< class Iter >
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
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
253 operator=( const ForwardRange2& r )
254 {
255 iterator_range_::operator=( r );
256 return *this;
257 }
258
259 sub_range& operator=( const sub_range& r )
260 {
261 iterator_range_::operator=( static_cast<const iterator_range_&>(r) );
262 return *this;
263 }
264
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
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