1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
4 Distributed under the Boost Software License, Version 1.0. (See accompanying
5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 ==============================================================================*/
7 #if !defined(FUSION_POP_BACK_09172005_1038)
8 #define FUSION_POP_BACK_09172005_1038
10 #include <boost/fusion/support/config.hpp>
11 #include <boost/fusion/view/iterator_range/iterator_range.hpp>
12 #include <boost/fusion/sequence/intrinsic/begin.hpp>
13 #include <boost/fusion/sequence/intrinsic/end.hpp>
14 #include <boost/fusion/sequence/intrinsic/empty.hpp>
15 #include <boost/fusion/iterator/iterator_adapter.hpp>
16 #include <boost/fusion/iterator/next.hpp>
17 #include <boost/mpl/minus.hpp>
18 #include <boost/mpl/int.hpp>
19 #include <boost/mpl/if.hpp>
21 namespace boost { namespace fusion
23 template <typename Iterator_, bool IsLast>
24 struct pop_back_iterator
26 pop_back_iterator<Iterator_, IsLast>
29 typedef iterator_adapter<
30 pop_back_iterator<Iterator_, IsLast>
34 static bool const is_last = IsLast;
36 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
37 pop_back_iterator(Iterator_ const& iterator_base)
38 : base_type(iterator_base) {}
40 template <typename BaseIterator>
43 typedef pop_back_iterator<BaseIterator, is_last> type;
45 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
47 call(BaseIterator const& i)
53 template <typename I, bool IsLast_>
54 struct equal_to_helper
55 : mpl::identity<typename I::iterator_base_type>
59 struct equal_to_helper<I, true>
61 typename I::iterator_base_type>
64 template <typename I1, typename I2>
66 : result_of::equal_to<
67 typename equal_to_helper<I1,
68 (I2::is_last && !I1::is_last)>::type
69 , typename equal_to_helper<I2,
70 (I1::is_last && !I2::is_last)>::type
74 template <typename First, typename Last>
77 typename result_of::distance<
78 typename First::iterator_base_type
79 , typename Last::iterator_base_type
81 , mpl::int_<(Last::is_last?1:0)>
86 template <typename Iterator, bool IsLast_>
89 typedef typename Iterator::iterator_base_type base_type;
92 result_of::prior<base_type>::type
95 typedef pop_back_iterator<base_prior, false> type;
97 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
99 call(Iterator const& i)
101 return type(fusion::prior(i.iterator_base));
105 template <typename Iterator>
106 struct prior_impl<Iterator, true>
108 // If this is the last iterator, we'll have to double back
109 typedef typename Iterator::iterator_base_type base_type;
113 typename result_of::prior<base_type>::type
117 typedef pop_back_iterator<base_prior, false> type;
119 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
121 call(Iterator const& i)
123 return type(fusion::prior(
124 fusion::prior(i.iterator_base)));
128 template <typename Iterator>
129 struct prior : prior_impl<Iterator, Iterator::is_last>
135 template <typename Sequence>
138 BOOST_MPL_ASSERT_NOT((result_of::empty<Sequence>));
140 typedef pop_back_iterator<
141 typename begin<Sequence>::type, false>
144 typedef pop_back_iterator<
145 typename end<Sequence>::type, true>
149 iterator_range<begin_type, end_type>
154 template <typename Sequence>
155 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
156 inline typename result_of::pop_back<Sequence const>::type
157 pop_back(Sequence const& seq)
159 typedef result_of::pop_back<Sequence const> comp;
160 typedef typename comp::begin_type begin_type;
161 typedef typename comp::end_type end_type;
162 typedef typename comp::type result;
165 begin_type(fusion::begin(seq))
166 , end_type(fusion::end(seq))