1 /*=============================================================================
2 Copyright (c) 2006 Eric Niebler
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 #ifndef FUSION_SEGMENTED_ITERATOR_RANGE_EAN_05032006_1027
9 #define FUSION_SEGMENTED_ITERATOR_RANGE_EAN_05032006_1027
11 #include <boost/mpl/bool.hpp>
12 #include <boost/mpl/minus.hpp>
13 #include <boost/mpl/next_prior.hpp>
14 #include <boost/mpl/and.hpp>
15 #include <boost/type_traits/remove_cv.hpp>
16 #include <boost/type_traits/remove_reference.hpp>
17 #include <boost/fusion/iterator/mpl/convert_iterator.hpp>
18 #include <boost/fusion/container/list/cons.hpp>
19 #include <boost/fusion/view/joint_view.hpp>
20 #include <boost/fusion/view/single_view.hpp>
21 #include <boost/fusion/view/transform_view.hpp>
22 #include <boost/fusion/view/iterator_range.hpp>
23 #include <boost/fusion/view/ext_/multiple_view.hpp>
24 #include <boost/fusion/view/ext_/segmented_iterator.hpp>
25 #include <boost/fusion/adapted/mpl/mpl_iterator.hpp>
27 namespace boost
{ namespace fusion
31 ////////////////////////////////////////////////////////////////////////////
32 template<typename Cons
, typename State
= nil
>
35 template<typename Car
, typename Cdr
, typename State
>
36 struct reverse_cons
<cons
<Car
, Cdr
>, State
>
38 typedef reverse_cons
<Cdr
, cons
<Car
, State
> > reverse
;
39 typedef typename
reverse::type type
;
41 static type
call(cons
<Car
, Cdr
> const &cons
, State
const &state
= State())
43 return reverse::call(cons
.cdr
, fusion::make_cons(cons
.car
, state
));
47 template<typename State
>
48 struct reverse_cons
<nil
, State
>
52 static State
const &call(nil
const &, State
const &state
= State())
58 ////////////////////////////////////////////////////////////////////////////
63 struct center_view
{};
65 template<typename Tag
>
66 struct segmented_view_tag
;
68 ////////////////////////////////////////////////////////////////////////////
69 // a segmented view of that includes all elements either to the
70 // right or the left of a segmented iterator.
71 template<typename Tag
, typename Cons1
, typename Cons2
= void_
>
73 : sequence_base
<segmented_view
<Tag
, Cons1
, Cons2
> >
75 typedef segmented_view_tag
<Tag
> fusion_tag
;
76 typedef fusion_sequence_tag tag
; // this gets picked up by MPL
77 typedef mpl::true_ is_view
;
78 typedef forward_traversal_tag category
;
80 explicit segmented_view(Cons1
const &cons
)
84 typedef Cons1 cons_type
;
85 cons_type
const &cons
;
88 // a segmented view that contains all the elements in between
89 // two segmented iterators
90 template<typename Cons1
, typename Cons2
>
91 struct segmented_view
<center_view
, Cons1
, Cons2
>
92 : sequence_base
<segmented_view
<center_view
, Cons1
, Cons2
> >
94 typedef segmented_view_tag
<center_view
> fusion_tag
;
95 typedef fusion_sequence_tag tag
; // this gets picked up by MPL
96 typedef mpl::true_ is_view
;
97 typedef forward_traversal_tag category
;
99 segmented_view(Cons1
const &lcons
, Cons2
const &rcons
)
104 typedef Cons1 left_cons_type
;
105 typedef Cons2 right_cons_type
;
107 left_cons_type
const &left_cons
;
108 right_cons_type
const &right_cons
;
111 ////////////////////////////////////////////////////////////////////////////
112 // Used to transform a sequence of segments. The first segment is
113 // bounded by RightCons, and the last segment is bounded by LeftCons
114 // and all the others are passed through unchanged.
115 template<typename RightCons
, typename LeftCons
= RightCons
>
116 struct segments_transform
118 explicit segments_transform(RightCons
const &cons_
)
123 segments_transform(RightCons
const &right_cons_
, LeftCons
const &left_cons_
)
124 : right_cons(right_cons_
)
125 , left_cons(left_cons_
)
128 template<typename First
, typename Second
>
131 template<typename Second
>
132 struct result_
<right_view
, Second
>
134 typedef segmented_view
<right_view
, RightCons
> type
;
137 template<typename Second
>
138 struct result_
<left_view
, Second
>
140 typedef segmented_view
<left_view
, LeftCons
> type
;
143 template<typename Second
>
144 struct result_
<full_view
, Second
>
149 template<typename Sig
>
152 template<typename This
, typename First
, typename Second
>
153 struct result
<This(First
, Second
)>
155 typename remove_cv
<typename remove_reference
<First
>::type
>::type
156 , typename remove_cv
<typename remove_reference
<Second
>::type
>::type
160 template<typename Second
>
161 segmented_view
<right_view
, RightCons
> operator ()(right_view
, Second
&second
) const
163 return segmented_view
<right_view
, RightCons
>(this->right_cons
);
166 template<typename Second
>
167 segmented_view
<left_view
, LeftCons
> operator ()(left_view
, Second
&second
) const
169 return segmented_view
<left_view
, LeftCons
>(this->left_cons
);
172 template<typename Second
>
173 Second
&operator ()(full_view
, Second
&second
) const
179 RightCons
const &right_cons
;
180 LeftCons
const &left_cons
;
183 } // namespace detail
187 ////////////////////////////////////////////////////////////////////////////
188 template<typename Tag
>
189 struct is_segmented_impl
<detail::segmented_view_tag
<Tag
> >
191 template<typename Sequence
>
197 ////////////////////////////////////////////////////////////////////////////
199 struct segments_impl
<detail::segmented_view_tag
<detail::right_view
> >
203 , typename Cdr
= typename
Sequence::cons_type::cdr_type
207 typedef typename
Sequence::cons_type::car_type segmented_range
;
208 typedef typename
result_of::size
<segmented_range
>::type size
;
209 typedef typename
mpl::prior
<size
>::type size_minus_1
;
210 typedef detail::segments_transform
<Cdr
> tfx
;
212 single_view
<detail::right_view
> const
213 , multiple_view
<size_minus_1
, detail::full_view
> const
215 typedef transform_view
<mask
const, segmented_range
const, tfx
> type
;
217 static type
call(Sequence
&seq
)
221 make_single_view(detail::right_view())
222 , make_multiple_view
<size_minus_1
>(detail::full_view())
230 template<typename Sequence
>
231 struct apply
<Sequence
, nil
>
233 typedef typename
Sequence::cons_type::car_type segmented_range
;
234 typedef typename
segmented_range::iterator_type begin
;
235 typedef typename
segmented_range::sequence_non_ref_type sequence_type
;
236 typedef typename
result_of::end
<sequence_type
>::type end
;
237 typedef iterator_range
<begin
, end
> range
;
238 typedef single_view
<range
> type
;
240 static type
call(Sequence
&seq
)
242 return type(range(seq
.cons
.car
.where_
, fusion::end(seq
.cons
.car
.sequence
)));
247 ////////////////////////////////////////////////////////////////////////////
249 struct segments_impl
<detail::segmented_view_tag
<detail::left_view
> >
253 , typename Cdr
= typename
Sequence::cons_type::cdr_type
257 typedef typename
Sequence::cons_type::car_type right_segmented_range
;
258 typedef typename
right_segmented_range::sequence_type sequence_type
;
259 typedef typename
right_segmented_range::iterator_type iterator_type
;
261 typedef iterator_range
<
262 typename
result_of::begin
<sequence_type
>::type
263 , typename
result_of::next
<iterator_type
>::type
266 typedef detail::segments_transform
<Cdr
> tfx
;
267 typedef typename
result_of::size
<segmented_range
>::type size
;
268 typedef typename
mpl::prior
<size
>::type size_minus_1
;
270 multiple_view
<size_minus_1
, detail::full_view
> const
271 , single_view
<detail::left_view
> const
273 typedef transform_view
<mask
const, segmented_range
const, tfx
> type
;
275 static type
call(Sequence
&seq
)
279 make_multiple_view
<size_minus_1
>(detail::full_view())
280 , make_single_view(detail::left_view())
282 , segmented_range(fusion::begin(seq
.cons
.car
.sequence
), fusion::next(seq
.cons
.car
.where_
))
288 template<typename Sequence
>
289 struct apply
<Sequence
, nil
>
291 typedef typename
Sequence::cons_type::car_type segmented_range
;
292 typedef typename
segmented_range::sequence_non_ref_type sequence_type
;
293 typedef typename
result_of::begin
<sequence_type
>::type begin
;
294 typedef typename
segmented_range::iterator_type end
;
295 typedef iterator_range
<begin
, end
> range
;
296 typedef single_view
<range
> type
;
298 static type
call(Sequence
&seq
)
300 return type(range(fusion::begin(seq
.cons
.car
.sequence
), seq
.cons
.car
.where_
));
305 ////////////////////////////////////////////////////////////////////////////
307 struct segments_impl
<detail::segmented_view_tag
<detail::center_view
> >
309 template<typename Sequence
>
312 typedef typename
Sequence::right_cons_type right_cons_type
;
313 typedef typename
Sequence::left_cons_type left_cons_type
;
314 typedef typename
right_cons_type::car_type right_segmented_range
;
315 typedef typename
left_cons_type::car_type left_segmented_range
;
317 typedef iterator_range
<
318 typename
result_of::begin
<left_segmented_range
>::type
319 , typename
result_of::next
<typename
result_of::begin
<right_segmented_range
>::type
>::type
322 typedef typename
mpl::minus
<
323 typename
result_of::size
<segmented_range
>::type
325 >::type size_minus_2
;
327 BOOST_MPL_ASSERT_RELATION(0, <=, size_minus_2::value
);
329 typedef detail::segments_transform
<
330 typename
left_cons_type::cdr_type
331 , typename
right_cons_type::cdr_type
335 multiple_view
<size_minus_2
, detail::full_view
> const
336 , single_view
<detail::left_view
> const
340 single_view
<detail::right_view
> const
344 typedef transform_view
<mask
const, segmented_range
const, tfx
> type
;
346 static type
call(Sequence
&seq
)
349 make_multiple_view
<size_minus_2
>(detail::full_view())
350 , make_single_view(detail::left_view())
353 mask(make_single_view(detail::right_view()), lmask
)
354 , segmented_range(fusion::begin(seq
.left_cons
.car
), fusion::next(fusion::begin(seq
.right_cons
.car
)))
355 , tfx(seq
.left_cons
.cdr
, seq
.right_cons
.cdr
)
362 // specialize iterator_range for use with segmented iterators, so that
363 // it presents a segmented view of the range.
364 template<typename First
, typename Last
>
365 struct iterator_range
;
367 template<typename First
, typename Last
>
368 struct iterator_range
<segmented_iterator
<First
>, segmented_iterator
<Last
> >
369 : sequence_base
<iterator_range
<segmented_iterator
<First
>, segmented_iterator
<Last
> > >
371 typedef typename convert_iterator
<segmented_iterator
<First
> >::type begin_type
;
372 typedef typename convert_iterator
<segmented_iterator
<Last
> >::type end_type
;
373 typedef typename
detail::reverse_cons
<First
>::type begin_cons_type
;
374 typedef typename
detail::reverse_cons
<Last
>::type end_cons_type
;
375 typedef iterator_range_tag fusion_tag
;
376 typedef fusion_sequence_tag tag
; // this gets picked up by MPL
377 typedef typename
traits::category_of
<begin_type
>::type category
;
378 typedef typename
result_of::distance
<begin_type
, end_type
>::type size
;
379 typedef mpl::true_ is_view
;
381 iterator_range(segmented_iterator
<First
> const& first_
, segmented_iterator
<Last
> const& last_
)
382 : first(convert_iterator
<segmented_iterator
<First
> >::call(first_
))
383 , last(convert_iterator
<segmented_iterator
<Last
> >::call(last_
))
384 , first_cons(detail::reverse_cons
<First
>::call(first_
.cons()))
385 , last_cons(detail::reverse_cons
<Last
>::call(last_
.cons()))
391 begin_cons_type first_cons
;
392 end_cons_type last_cons
;
398 template<typename Cons1
, typename Cons2
>
403 template<typename Car1
, typename Cdr1
, typename Car2
, typename Cdr2
>
404 struct same_segment
<cons
<Car1
, Cdr1
>, cons
<Car2
, Cdr2
> >
406 traits::is_segmented
<Car1
>
407 , is_same
<Car1
, Car2
>
411 ////////////////////////////////////////////////////////////////////////////
412 template<typename Cons1
, typename Cons2
>
415 ////////////////////////////////////////////////////////////////////////////
416 template<typename Cons1
, typename Cons2
, bool SameSegment
>
419 typedef segments_gen
<typename
Cons1::cdr_type
, typename
Cons2::cdr_type
> gen
;
420 typedef typename
gen::type type
;
422 static type
call(Cons1
const &cons1
, Cons2
const &cons2
)
424 return gen::call(cons1
.cdr
, cons2
.cdr
);
428 template<typename Cons1
, typename Cons2
>
429 struct segments_gen2
<Cons1
, Cons2
, false>
431 typedef segmented_view
<center_view
, Cons1
, Cons2
> view
;
432 typedef typename
result_of::segments
<view
>::type type
;
434 static type
call(Cons1
const &cons1
, Cons2
const &cons2
)
436 view
v(cons1
, cons2
);
437 return fusion::segments(v
);
441 template<typename Car1
, typename Car2
>
442 struct segments_gen2
<cons
<Car1
>, cons
<Car2
>, false>
444 typedef iterator_range
<
445 typename
Car1::iterator_type
446 , typename
Car2::iterator_type
449 typedef single_view
<range
> type
;
451 static type
call(cons
<Car1
> const &cons1
, cons
<Car2
> const &cons2
)
453 return type(range(cons1
.car
.where_
, cons2
.car
.where_
));
457 ////////////////////////////////////////////////////////////////////////////
458 template<typename Cons1
, typename Cons2
>
460 : segments_gen2
<Cons1
, Cons2
, same_segment
<Cons1
, Cons2
>::value
>
463 template<typename Car
, typename Cdr
>
464 struct segments_gen
<cons
<Car
, Cdr
>, nil
>
466 typedef segmented_view
<right_view
, cons
<Car
, Cdr
> > view
;
467 typedef typename
result_of::segments
<view
>::type type
;
469 static type
call(cons
<Car
, Cdr
> const &cons
, nil
const &)
472 return fusion::segments(v
);
477 struct segments_gen
<nil
, nil
>
481 static type
call(nil
const &, nil
const &)
486 } // namespace detail
490 template<typename Tag
>
491 struct is_segmented_impl
;
493 // An iterator_range of segmented_iterators is segmented
495 struct is_segmented_impl
<iterator_range_tag
>
497 template<typename Iterator
>
498 struct is_segmented_iterator
: mpl::false_
{};
500 template<typename Cons
>
501 struct is_segmented_iterator
<segmented_iterator
<Cons
> > : mpl::true_
{};
503 template<typename Sequence
>
506 is_segmented_iterator
<typename
Sequence::begin_type
>
507 , is_segmented_iterator
<typename
Sequence::end_type
>
512 template<typename Sequence
>
513 struct segments_impl
;
516 struct segments_impl
<iterator_range_tag
>
518 template<typename Sequence
>
521 typedef typename
Sequence::begin_cons_type begin_cons
;
522 typedef typename
Sequence::end_cons_type end_cons
;
524 typedef detail::segments_gen
<begin_cons
, end_cons
> gen
;
525 typedef typename
gen::type type
;
527 static type
call(Sequence
&sequence
)
529 return gen::call(sequence
.first_cons
, sequence
.last_cons
);