any_if.hpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Hartmut Kaiser
  3. Copyright (c) 2001-2011 Joel de Guzman
  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(BOOST_SPIRIT_ANY_IF_MARCH_30_2007_1220PM)
  8. #define BOOST_SPIRIT_ANY_IF_MARCH_30_2007_1220PM
  9. #if defined(_MSC_VER)
  10. #pragma once
  11. #endif
  12. #include <boost/fusion/include/equal_to.hpp>
  13. #include <boost/fusion/include/next.hpp>
  14. #include <boost/fusion/include/deref.hpp>
  15. #include <boost/fusion/include/value_of.hpp>
  16. #include <boost/fusion/include/begin.hpp>
  17. #include <boost/fusion/include/end.hpp>
  18. #include <boost/fusion/include/is_sequence.hpp>
  19. #include <boost/fusion/include/any.hpp>
  20. #include <boost/spirit/home/support/unused.hpp>
  21. #include <boost/mpl/bool.hpp>
  22. #include <boost/mpl/apply.hpp>
  23. #include <boost/mpl/if.hpp>
  24. #include <boost/mpl/identity.hpp>
  25. #include <boost/mpl/and.hpp>
  26. #include <boost/mpl/not.hpp>
  27. namespace boost { namespace spirit
  28. {
  29. ///////////////////////////////////////////////////////////////////////////
  30. // This is a special version for a binary fusion::any. The predicate
  31. // is used to decide whether to advance the second iterator or not.
  32. // This is needed for sequences containing components with unused
  33. // attributes. The second iterator is advanced only if the attribute
  34. // of the corresponding component iterator is not unused.
  35. ///////////////////////////////////////////////////////////////////////////
  36. namespace detail
  37. {
  38. ///////////////////////////////////////////////////////////////////////
  39. template <typename Iterator, typename Pred>
  40. struct apply_predicate
  41. : mpl::apply1<Pred, typename fusion::result_of::value_of<Iterator>::type>
  42. {};
  43. ///////////////////////////////////////////////////////////////////////
  44. // if the predicate is true, attribute_next returns next(Iterator2),
  45. // otherwise Iterator2
  46. namespace result_of
  47. {
  48. template <
  49. typename Iterator1, typename Iterator2, typename Last2
  50. , typename Pred>
  51. struct attribute_next
  52. {
  53. typedef mpl::and_<
  54. apply_predicate<Iterator1, Pred>
  55. , mpl::not_<fusion::result_of::equal_to<Iterator2, Last2> >
  56. > pred;
  57. typedef typename
  58. mpl::eval_if<
  59. pred
  60. , fusion::result_of::next<Iterator2>
  61. , mpl::identity<Iterator2>
  62. >::type
  63. type;
  64. template <typename Iterator>
  65. static type
  66. call(Iterator const& i, mpl::true_)
  67. {
  68. return fusion::next(i);
  69. }
  70. template <typename Iterator>
  71. static type
  72. call(Iterator const& i, mpl::false_)
  73. {
  74. return i;
  75. }
  76. template <typename Iterator>
  77. static type
  78. call(Iterator const& i)
  79. {
  80. return call(i, pred());
  81. }
  82. };
  83. }
  84. template <
  85. typename Pred, typename Iterator1, typename Last2
  86. , typename Iterator2>
  87. inline typename
  88. result_of::attribute_next<Iterator1, Iterator2, Last2, Pred
  89. >::type const
  90. attribute_next(Iterator2 const& i)
  91. {
  92. return result_of::attribute_next<
  93. Iterator1, Iterator2, Last2, Pred>::call(i);
  94. }
  95. ///////////////////////////////////////////////////////////////////////
  96. // if the predicate is true, attribute_value returns deref(Iterator2),
  97. // otherwise unused
  98. namespace result_of
  99. {
  100. template <
  101. typename Iterator1, typename Iterator2, typename Last2
  102. , typename Pred>
  103. struct attribute_value
  104. {
  105. typedef mpl::and_<
  106. apply_predicate<Iterator1, Pred>
  107. , mpl::not_<fusion::result_of::equal_to<Iterator2, Last2> >
  108. > pred;
  109. typedef typename
  110. mpl::eval_if<
  111. pred
  112. , fusion::result_of::deref<Iterator2>
  113. , mpl::identity<unused_type const>
  114. >::type
  115. type;
  116. template <typename Iterator>
  117. static type
  118. call(Iterator const& i, mpl::true_)
  119. {
  120. return fusion::deref(i);
  121. }
  122. template <typename Iterator>
  123. static type
  124. call(Iterator const&, mpl::false_)
  125. {
  126. return unused;
  127. }
  128. template <typename Iterator>
  129. static type
  130. call(Iterator const& i)
  131. {
  132. return call(i, pred());
  133. }
  134. };
  135. }
  136. template <
  137. typename Pred, typename Iterator1, typename Last2
  138. , typename Iterator2>
  139. inline typename
  140. result_of::attribute_value<Iterator1, Iterator2, Last2, Pred
  141. >::type
  142. attribute_value(Iterator2 const& i)
  143. {
  144. return result_of::attribute_value<
  145. Iterator1, Iterator2, Last2, Pred>::call(i);
  146. }
  147. ///////////////////////////////////////////////////////////////////////
  148. template <
  149. typename Pred, typename First1, typename Last1, typename First2
  150. , typename Last2, typename F>
  151. inline bool
  152. any_if (First1 const&, First2 const&, Last1 const&, Last2 const&
  153. , F const&, mpl::true_)
  154. {
  155. return false;
  156. }
  157. template <
  158. typename Pred, typename First1, typename Last1, typename First2
  159. , typename Last2, typename F>
  160. inline bool
  161. any_if (First1 const& first1, First2 const& first2, Last1 const& last1
  162. , Last2 const& last2, F& f, mpl::false_)
  163. {
  164. typename result_of::attribute_value<First1, First2, Last2, Pred>::type
  165. attribute = spirit::detail::attribute_value<Pred, First1, Last2>(first2);
  166. return f(*first1, attribute) ||
  167. detail::any_if<Pred>(
  168. fusion::next(first1)
  169. , attribute_next<Pred, First1, Last2>(first2)
  170. , last1, last2
  171. , f
  172. , fusion::result_of::equal_to<
  173. typename fusion::result_of::next<First1>::type, Last1>());
  174. }
  175. }
  176. template <typename Pred, typename Sequence1, typename Sequence2, typename F>
  177. inline bool
  178. any_if(Sequence1 const& seq1, Sequence2& seq2, F f, Pred)
  179. {
  180. return detail::any_if<Pred>(
  181. fusion::begin(seq1), fusion::begin(seq2)
  182. , fusion::end(seq1), fusion::end(seq2)
  183. , f
  184. , fusion::result_of::equal_to<
  185. typename fusion::result_of::begin<Sequence1>::type
  186. , typename fusion::result_of::end<Sequence1>::type>());
  187. }
  188. template <typename Pred, typename Sequence, typename F>
  189. inline bool
  190. any_if(Sequence const& seq, unused_type const, F f, Pred)
  191. {
  192. return fusion::any(seq, f);
  193. }
  194. }}
  195. #endif