find_if.hpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2007 Dan Marsden
  4. Copyright (c) 2009 Christopher Schmidt
  5. Copyright (c) 2018 Kohei Takahashi
  6. Distributed under the Boost Software License, Version 1.0. (See accompanying
  7. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. ==============================================================================*/
  9. #if !defined(FUSION_FIND_IF_05052005_1107)
  10. #define FUSION_FIND_IF_05052005_1107
  11. #include <boost/fusion/support/config.hpp>
  12. #include <boost/mpl/apply.hpp>
  13. #include <boost/mpl/eval_if.hpp>
  14. #include <boost/mpl/identity.hpp>
  15. #include <boost/mpl/or.hpp>
  16. #include <boost/fusion/iterator/advance.hpp>
  17. #include <boost/fusion/iterator/distance.hpp>
  18. #include <boost/fusion/iterator/equal_to.hpp>
  19. #include <boost/fusion/iterator/next.hpp>
  20. #include <boost/fusion/sequence/intrinsic/begin.hpp>
  21. #include <boost/fusion/sequence/intrinsic/end.hpp>
  22. #include <boost/fusion/support/category_of.hpp>
  23. #include <boost/core/enable_if.hpp>
  24. namespace boost { namespace fusion { namespace detail
  25. {
  26. template <typename Iterator, typename Pred>
  27. struct apply_filter
  28. {
  29. typedef typename mpl::apply1<
  30. Pred, Iterator>::type type;
  31. BOOST_STATIC_CONSTANT(int, value = type::value);
  32. };
  33. template <typename First, typename Last, typename Pred>
  34. struct main_find_if;
  35. template <typename First, typename Last, typename Pred>
  36. struct recursive_find_if
  37. {
  38. typedef typename
  39. main_find_if<
  40. typename result_of::next<First>::type, Last, Pred
  41. >::type
  42. type;
  43. };
  44. template <typename First, typename Last, typename Pred>
  45. struct main_find_if
  46. {
  47. typedef mpl::or_<
  48. result_of::equal_to<First, Last>
  49. , apply_filter<First, Pred> >
  50. filter;
  51. typedef typename
  52. mpl::eval_if<
  53. filter
  54. , mpl::identity<First>
  55. , recursive_find_if<First, Last, Pred>
  56. >::type
  57. type;
  58. };
  59. template<
  60. typename First, typename Last,
  61. typename Pred, bool>
  62. struct choose_find_if;
  63. template<typename First, typename Last, typename Pred>
  64. struct choose_find_if<First, Last, Pred, false>
  65. : main_find_if<First, Last, Pred>
  66. {};
  67. template<typename Iter, typename Pred, int n, int unrolling>
  68. struct unroll_again;
  69. template <typename Iter, typename Pred, int offset>
  70. struct apply_offset_filter
  71. {
  72. typedef typename result_of::advance_c<Iter, offset>::type Shifted;
  73. typedef typename
  74. mpl::apply1<
  75. Pred
  76. , Shifted
  77. >::type
  78. type;
  79. BOOST_STATIC_CONSTANT(int, value = type::value);
  80. };
  81. template<typename Iter, typename Pred, int n>
  82. struct unrolled_find_if
  83. {
  84. typedef typename mpl::eval_if<
  85. apply_filter<Iter, Pred>,
  86. mpl::identity<Iter>,
  87. mpl::eval_if<
  88. apply_offset_filter<Iter, Pred, 1>,
  89. result_of::advance_c<Iter, 1>,
  90. mpl::eval_if<
  91. apply_offset_filter<Iter, Pred, 2>,
  92. result_of::advance_c<Iter, 2>,
  93. mpl::eval_if<
  94. apply_offset_filter<Iter, Pred, 3>,
  95. result_of::advance_c<Iter, 3>,
  96. unroll_again<
  97. Iter,
  98. Pred,
  99. n,
  100. 4> > > > >::type type;
  101. };
  102. template<typename Iter, typename Pred>
  103. struct unrolled_find_if<Iter, Pred, 3>
  104. {
  105. typedef typename mpl::eval_if<
  106. apply_filter<Iter, Pred>,
  107. mpl::identity<Iter>,
  108. mpl::eval_if<
  109. apply_offset_filter<Iter, Pred, 1>,
  110. result_of::advance_c<Iter, 1>,
  111. mpl::eval_if<
  112. apply_offset_filter<Iter, Pred, 2>,
  113. result_of::advance_c<Iter, 2>,
  114. result_of::advance_c<Iter, 3> > > >::type type;
  115. };
  116. template<typename Iter, typename Pred>
  117. struct unrolled_find_if<Iter, Pred, 2>
  118. {
  119. typedef typename mpl::eval_if<
  120. apply_filter<Iter, Pred>,
  121. mpl::identity<Iter>,
  122. mpl::eval_if<
  123. apply_offset_filter<Iter, Pred, 1>,
  124. result_of::advance_c<Iter, 1>,
  125. result_of::advance_c<Iter, 2> > >::type type;
  126. };
  127. template<typename Iter, typename Pred>
  128. struct unrolled_find_if<Iter, Pred, 1>
  129. {
  130. typedef typename mpl::eval_if<
  131. apply_filter<Iter, Pred>,
  132. mpl::identity<Iter>,
  133. result_of::advance_c<Iter, 1> >::type type;
  134. };
  135. template<typename Iter, typename Pred, int n, int unrolling>
  136. struct unroll_again
  137. {
  138. typedef typename unrolled_find_if<
  139. typename result_of::advance_c<Iter, unrolling>::type,
  140. Pred,
  141. n-unrolling>::type type;
  142. };
  143. template<typename Iter, typename Pred>
  144. struct unrolled_find_if<Iter, Pred, 0>
  145. {
  146. typedef Iter type;
  147. };
  148. template<typename First, typename Last, typename Pred>
  149. struct choose_find_if<First, Last, Pred, true>
  150. {
  151. typedef typename result_of::distance<First, Last>::type N;
  152. typedef typename unrolled_find_if<First, Pred, N::value>::type type;
  153. };
  154. template <typename First, typename Last, typename Pred>
  155. struct static_find_if
  156. {
  157. typedef typename
  158. choose_find_if<
  159. First
  160. , Last
  161. , Pred
  162. , traits::is_random_access<First>::value
  163. >::type
  164. type;
  165. template <typename Iterator>
  166. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  167. static type
  168. recursive_call(Iterator const& iter, mpl::true_)
  169. {
  170. return iter;
  171. }
  172. template <typename Iterator>
  173. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  174. static type
  175. recursive_call(Iterator const& iter, mpl::false_)
  176. {
  177. return recursive_call(fusion::next(iter));
  178. }
  179. template <typename Iterator>
  180. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  181. static type
  182. recursive_call(Iterator const& iter)
  183. {
  184. typedef result_of::equal_to<Iterator, type> found;
  185. return recursive_call(iter, found());
  186. }
  187. template <typename Iterator>
  188. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  189. static typename boost::disable_if<traits::is_random_access<Iterator>, type>::type
  190. iter_call(Iterator const& iter)
  191. {
  192. return recursive_call(iter);
  193. }
  194. template <typename Iterator>
  195. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  196. static typename boost::enable_if<traits::is_random_access<Iterator>, type>::type
  197. iter_call(Iterator const& iter)
  198. {
  199. typedef typename result_of::distance<Iterator, type>::type N;
  200. return fusion::advance<N>(iter);
  201. }
  202. template <typename Sequence>
  203. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  204. static type
  205. call(Sequence& seq)
  206. {
  207. return iter_call(fusion::begin(seq));
  208. }
  209. };
  210. template <typename Sequence, typename Pred>
  211. struct result_of_find_if
  212. {
  213. typedef
  214. static_find_if<
  215. typename result_of::begin<Sequence>::type
  216. , typename result_of::end<Sequence>::type
  217. , Pred
  218. >
  219. filter;
  220. typedef typename filter::type type;
  221. };
  222. }}}
  223. #endif