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