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
21namespace 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
37 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
47 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
99 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
121 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
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

source code of include/boost/fusion/algorithm/transformation/pop_back.hpp