pop_back.hpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. ==============================================================================*/
  6. #if !defined(FUSION_POP_BACK_09172005_1038)
  7. #define FUSION_POP_BACK_09172005_1038
  8. #include <boost/fusion/support/config.hpp>
  9. #include <boost/fusion/view/iterator_range/iterator_range.hpp>
  10. #include <boost/fusion/sequence/intrinsic/begin.hpp>
  11. #include <boost/fusion/sequence/intrinsic/end.hpp>
  12. #include <boost/fusion/sequence/intrinsic/empty.hpp>
  13. #include <boost/fusion/iterator/iterator_adapter.hpp>
  14. #include <boost/fusion/iterator/next.hpp>
  15. #include <boost/mpl/minus.hpp>
  16. #include <boost/mpl/int.hpp>
  17. #include <boost/mpl/if.hpp>
  18. #ifdef _MSC_VER
  19. # pragma warning(push)
  20. # pragma warning(disable: 4512) // assignment operator could not be generated.
  21. #endif
  22. namespace boost { namespace fusion
  23. {
  24. template <typename Iterator_, bool IsLast>
  25. struct pop_back_iterator
  26. : iterator_adapter<
  27. pop_back_iterator<Iterator_, IsLast>
  28. , Iterator_>
  29. {
  30. typedef iterator_adapter<
  31. pop_back_iterator<Iterator_, IsLast>
  32. , Iterator_>
  33. base_type;
  34. static bool const is_last = IsLast;
  35. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  36. pop_back_iterator(Iterator_ const& iterator_base)
  37. : base_type(iterator_base) {}
  38. template <typename BaseIterator>
  39. struct make
  40. {
  41. typedef pop_back_iterator<BaseIterator, is_last> type;
  42. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  43. static type
  44. call(BaseIterator const& i)
  45. {
  46. return type(i);
  47. }
  48. };
  49. template <typename I, bool IsLast_>
  50. struct equal_to_helper
  51. : mpl::identity<typename I::iterator_base_type>
  52. {};
  53. template <typename I>
  54. struct equal_to_helper<I, true>
  55. : result_of::next<
  56. typename I::iterator_base_type>
  57. {};
  58. template <typename I1, typename I2>
  59. struct equal_to
  60. : result_of::equal_to<
  61. typename equal_to_helper<I1,
  62. (I2::is_last && !I1::is_last)>::type
  63. , typename equal_to_helper<I2,
  64. (I1::is_last && !I2::is_last)>::type
  65. >
  66. {};
  67. template <typename First, typename Last>
  68. struct distance
  69. : mpl::minus<
  70. typename result_of::distance<
  71. typename First::iterator_base_type
  72. , typename Last::iterator_base_type
  73. >::type
  74. , mpl::int_<(Last::is_last?1:0)>
  75. >::type
  76. {};
  77. template <typename Iterator, bool IsLast_>
  78. struct prior_impl
  79. {
  80. typedef typename Iterator::iterator_base_type base_type;
  81. typedef typename
  82. result_of::prior<base_type>::type
  83. base_prior;
  84. typedef pop_back_iterator<base_prior, false> type;
  85. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  86. static type
  87. call(Iterator const& i)
  88. {
  89. return type(fusion::prior(i.iterator_base));
  90. }
  91. };
  92. template <typename Iterator>
  93. struct prior_impl<Iterator, true>
  94. {
  95. // If this is the last iterator, we'll have to double back
  96. typedef typename Iterator::iterator_base_type base_type;
  97. typedef typename
  98. result_of::prior<
  99. typename result_of::prior<base_type>::type
  100. >::type
  101. base_prior;
  102. typedef pop_back_iterator<base_prior, false> type;
  103. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  104. static type
  105. call(Iterator const& i)
  106. {
  107. return type(fusion::prior(
  108. fusion::prior(i.iterator_base)));
  109. }
  110. };
  111. template <typename Iterator>
  112. struct prior : prior_impl<Iterator, Iterator::is_last>
  113. {};
  114. };
  115. namespace result_of
  116. {
  117. template <typename Sequence>
  118. struct pop_back
  119. {
  120. BOOST_MPL_ASSERT_NOT((result_of::empty<Sequence>));
  121. typedef pop_back_iterator<
  122. typename begin<Sequence>::type, false>
  123. begin_type;
  124. typedef pop_back_iterator<
  125. typename end<Sequence>::type, true>
  126. end_type;
  127. typedef
  128. iterator_range<begin_type, end_type>
  129. type;
  130. };
  131. }
  132. template <typename Sequence>
  133. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  134. inline typename result_of::pop_back<Sequence const>::type
  135. pop_back(Sequence const& seq)
  136. {
  137. typedef result_of::pop_back<Sequence const> comp;
  138. typedef typename comp::begin_type begin_type;
  139. typedef typename comp::end_type end_type;
  140. typedef typename comp::type result;
  141. return result(
  142. begin_type(fusion::begin(seq))
  143. , end_type(fusion::end(seq))
  144. );
  145. }
  146. }}
  147. #ifdef _MSC_VER
  148. # pragma warning(pop)
  149. #endif
  150. #endif