1 /*=============================================================================
2     Copyright (c) 2001-2011 Joel de Guzman
3 
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
9 
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>
20 
21 namespace boost { namespace fusion
22 {
23     template <typename Iterator_, bool IsLast>
24     struct pop_back_iterator
25         : iterator_adapter<
26             pop_back_iterator<Iterator_, IsLast>
27           , Iterator_>
28     {
29         typedef iterator_adapter<
30             pop_back_iterator<Iterator_, IsLast>
31           , Iterator_>
32         base_type;
33 
34         static bool const is_last = IsLast;
35 
36         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
pop_back_iteratorboost::fusion::pop_back_iterator37         pop_back_iterator(Iterator_ const& iterator_base)
38             : base_type(iterator_base) {}
39 
40         template <typename BaseIterator>
41         struct make
42         {
43             typedef pop_back_iterator<BaseIterator, is_last> type;
44 
45             BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
46             static type
callboost::fusion::pop_back_iterator::make47             call(BaseIterator const& i)
48             {
49                 return type(i);
50             }
51         };
52 
53         template <typename I, bool IsLast_>
54         struct equal_to_helper
55             : mpl::identity<typename I::iterator_base_type>
56         {};
57 
58         template <typename I>
59         struct equal_to_helper<I, true>
60             : result_of::next<
61                 typename I::iterator_base_type>
62         {};
63 
64         template <typename I1, typename I2>
65         struct equal_to
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
71             >
72         {};
73 
74         template <typename First, typename Last>
75         struct distance
76             : mpl::minus<
77                 typename result_of::distance<
78                     typename First::iterator_base_type
79                   , typename Last::iterator_base_type
80                 >::type
81               , mpl::int_<(Last::is_last?1:0)>
82             >::type
83         {};
84 
85 
86         template <typename Iterator, bool IsLast_>
87         struct prior_impl
88         {
89             typedef typename Iterator::iterator_base_type base_type;
90 
91             typedef typename
92                 result_of::prior<base_type>::type
93             base_prior;
94 
95             typedef pop_back_iterator<base_prior, false> type;
96 
97             BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
98             static type
callboost::fusion::pop_back_iterator::prior_impl99             call(Iterator const& i)
100             {
101                 return type(fusion::prior(i.iterator_base));
102             }
103         };
104 
105         template <typename Iterator>
106         struct prior_impl<Iterator, true>
107         {
108             // If this is the last iterator, we'll have to double back
109             typedef typename Iterator::iterator_base_type base_type;
110 
111             typedef typename
112                 result_of::prior<
113                   typename result_of::prior<base_type>::type
114                 >::type
115             base_prior;
116 
117             typedef pop_back_iterator<base_prior, false> type;
118 
119             BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
120             static type
callboost::fusion::pop_back_iterator::prior_impl121             call(Iterator const& i)
122             {
123                 return type(fusion::prior(
124                     fusion::prior(i.iterator_base)));
125             }
126         };
127 
128         template <typename Iterator>
129         struct prior : prior_impl<Iterator, Iterator::is_last>
130         {};
131     };
132 
133     namespace result_of
134     {
135         template <typename Sequence>
136         struct pop_back
137         {
138             BOOST_MPL_ASSERT_NOT((result_of::empty<Sequence>));
139 
140             typedef pop_back_iterator<
141                 typename begin<Sequence>::type, false>
142             begin_type;
143 
144             typedef pop_back_iterator<
145                 typename end<Sequence>::type, true>
146             end_type;
147 
148             typedef
149                 iterator_range<begin_type, end_type>
150             type;
151         };
152     }
153 
154     template <typename Sequence>
155     BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
156     inline typename result_of::pop_back<Sequence const>::type
pop_back(Sequence const & seq)157     pop_back(Sequence const& seq)
158     {
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;
163 
164         return result(
165             begin_type(fusion::begin(seq))
166           , end_type(fusion::end(seq))
167         );
168     }
169 }}
170 
171 #endif
172 
173