| /*============================================================================= |
| Copyright (c) 2006 Eric Niebler |
| |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| ==============================================================================*/ |
| #if !defined(FIND_IF_S_05152006_1027) |
| #define FIND_IF_S_05152006_1027 |
| |
| #include <boost/mpl/not.hpp> |
| #include <boost/mpl/assert.hpp> |
| #include <boost/mpl/eval_if.hpp> |
| #include <boost/type_traits/is_const.hpp> |
| #include <boost/utility/enable_if.hpp> |
| #include <boost/type_traits/is_same.hpp> |
| #include <boost/fusion/algorithm/query/find_if.hpp> |
| #include <boost/fusion/container/list/cons.hpp> |
| #include <boost/fusion/sequence/intrinsic/ext_/segments.hpp> |
| #include <boost/fusion/view/ext_/segmented_iterator.hpp> |
| #include <boost/fusion/view/ext_/segmented_iterator_range.hpp> |
| #include <boost/fusion/support/ext_/is_segmented.hpp> |
| |
| // fwd declarations |
| namespace boost { namespace fusion |
| { |
| namespace detail |
| { |
| template<typename Sequence, typename Pred, bool IsSegmented = traits::is_segmented<Sequence>::value> |
| struct static_find_if_s_recurse; |
| } |
| |
| namespace result_of |
| { |
| template <typename Sequence, typename Pred> |
| struct find_if_s; |
| } |
| }} |
| |
| namespace boost { namespace fusion { namespace detail |
| { |
| |
| template<typename Sequence, typename Where, bool IsSegmented = traits::is_segmented<Sequence>::value> |
| struct is_found |
| : mpl::not_<result_of::equal_to<Where, typename result_of::end<Sequence>::type> > |
| {}; |
| |
| template<typename Sequence, typename Cons> |
| struct is_found<Sequence, Cons, true> |
| : mpl::not_<is_same<nil, Cons> > |
| {}; |
| |
| template< |
| typename SegmentedRange |
| , typename Where |
| , typename Sequence = typename remove_reference< |
| typename result_of::deref< |
| typename SegmentedRange::iterator_type |
| >::type |
| >::type |
| , bool IsSegmented = traits::is_segmented<Sequence>::value |
| > |
| struct as_segmented_cons |
| { |
| typedef cons< |
| SegmentedRange |
| , cons<segmented_range<Sequence, Where, false> > |
| > type; |
| |
| static type call(SegmentedRange const &range, Where const &where) |
| { |
| return fusion::make_cons( |
| range |
| , fusion::make_cons( |
| segmented_range<Sequence, Where, false>(*fusion::begin(range), where) |
| ) |
| ); |
| } |
| }; |
| |
| template< |
| typename SegmentedRange |
| , typename Where |
| , typename Sequence |
| > |
| struct as_segmented_cons<SegmentedRange, Where, Sequence, true> |
| { |
| typedef cons<SegmentedRange, Where> type; |
| |
| static type call(SegmentedRange const &range, Where const &where) |
| { |
| return fusion::make_cons(range, where); |
| } |
| }; |
| |
| template< |
| typename SegmentedRange |
| , typename Pred |
| , bool IsEmpty = is_empty<SegmentedRange>::value |
| > |
| struct static_find_if_s_seg |
| { |
| typedef typename SegmentedRange::iterator_type first; |
| typedef typename result_of::deref<first>::type segment_ref; |
| typedef typename remove_reference<segment_ref>::type segment; |
| typedef static_find_if_s_recurse<segment, Pred> where; |
| typedef range_next<SegmentedRange> next; |
| typedef is_found<segment, typename where::type> is_found; |
| typedef as_segmented_cons<SegmentedRange, typename where::type> found; |
| typedef static_find_if_s_seg<typename next::type, Pred> not_found; |
| typedef typename mpl::eval_if<is_found, found, not_found>::type type; |
| |
| static type call(SegmentedRange const &range) |
| { |
| return call_(range, is_found()); |
| } |
| |
| private: |
| static type call_(SegmentedRange const &range, mpl::true_) |
| { |
| return found::call(range, where::call(*range.where_)); |
| } |
| |
| static type call_(SegmentedRange const &range, mpl::false_) |
| { |
| return not_found::call(next::call(range)); |
| } |
| }; |
| |
| template< |
| typename SegmentedRange |
| , typename Pred |
| > |
| struct static_find_if_s_seg<SegmentedRange, Pred, true> |
| { |
| typedef nil type; |
| |
| static type call(SegmentedRange const &) |
| { |
| return nil(); |
| } |
| }; |
| |
| template<typename Sequence, typename Pred> |
| struct static_find_if_s_recurse<Sequence, Pred, true> |
| { |
| typedef typename as_segmented_range<Sequence>::type range; |
| typedef static_find_if_s_seg<range, Pred> find_if; |
| typedef typename find_if::type type; |
| |
| static type call(Sequence &seq) |
| { |
| return find_if::call(range(fusion::segments(seq))); |
| } |
| }; |
| |
| template<typename Sequence, typename Pred> |
| struct static_find_if_s_recurse<Sequence, Pred, false> |
| { |
| typedef typename result_of::find_if<Sequence, Pred>::type type; |
| |
| static type call(Sequence &seq) |
| { |
| return fusion::find_if<Pred>(seq); |
| } |
| }; |
| |
| template<typename Sequence, typename Pred, bool IsSegmented = traits::is_segmented<Sequence>::value> |
| struct static_find_if_s |
| : static_find_if_s_recurse<Sequence, Pred, IsSegmented> |
| {}; |
| |
| template<typename Sequence, typename Pred> |
| struct static_find_if_s<Sequence, Pred, true> |
| { |
| typedef typename as_segmented_range<Sequence>::type range; |
| typedef static_find_if_s_recurse<Sequence, Pred> find_if; |
| typedef typename find_if::type found; |
| |
| typedef segmented_iterator<typename reverse_cons<found>::type> type; |
| |
| static type call(Sequence &seq) |
| { |
| return type(reverse_cons<found>::call(find_if::call(seq))); |
| } |
| }; |
| }}} |
| |
| namespace boost { namespace fusion |
| { |
| namespace result_of |
| { |
| template <typename Sequence, typename Pred> |
| struct find_if_s |
| { |
| typedef typename |
| detail::static_find_if_s< |
| Sequence |
| , Pred |
| >::type |
| type; |
| }; |
| } |
| |
| template <typename Pred, typename Sequence> |
| typename lazy_disable_if< |
| is_const<Sequence> |
| , result_of::find_if_s<Sequence, Pred> |
| >::type |
| find_if_s(Sequence& seq) |
| { |
| return detail::static_find_if_s<Sequence, Pred>::call(seq); |
| } |
| |
| template <typename Pred, typename Sequence> |
| typename result_of::find_if_s<Sequence const, Pred>::type |
| find_if_s(Sequence const& seq) |
| { |
| return detail::static_find_if_s<Sequence const, Pred>::call(seq); |
| } |
| }} |
| |
| #endif |