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