diff --git a/include/boost/fusion/algorithm/query/detail/find_if.hpp b/include/boost/fusion/algorithm/query/detail/find_if.hpp index a82c040b..cf0cc6b7 100644 --- a/include/boost/fusion/algorithm/query/detail/find_if.hpp +++ b/include/boost/fusion/algorithm/query/detail/find_if.hpp @@ -1,5 +1,6 @@ /*============================================================================= Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2007 Dan Marsden 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) @@ -16,18 +17,22 @@ #include #include #include +#include +#include +#include +#include +#include -namespace boost { namespace fusion { namespace detail +namespace boost { namespace fusion { + struct random_access_traversal_tag; +namespace detail { template struct apply_filter { - typedef typename - mpl::apply1< - Pred - , typename result_of::value_of::type - >::type - type; + typedef typename mpl::apply1< + Pred, typename result_of::value_of::type>::type type; + BOOST_STATIC_CONSTANT(int, value = type::value); }; template @@ -60,37 +65,166 @@ namespace boost { namespace fusion { namespace detail type; }; + template< + typename First, typename Last, + typename Pred, bool> + struct choose_find_if; + + template + struct choose_find_if + : main_find_if + {}; + + template + struct unroll_again; + + template + struct apply_offset_filter + { + typedef typename result_of::advance_c::type Shifted; + typedef typename + mpl::apply1< + Pred + , typename result_of::value_of::type + >::type + type; + BOOST_STATIC_CONSTANT(int, value = type::value); + }; + + template + struct unrolled_find_if + { + typedef typename mpl::eval_if< + apply_filter, + mpl::identity, + mpl::eval_if< + apply_offset_filter, + result_of::advance_c, + mpl::eval_if< + apply_offset_filter, + result_of::advance_c, + mpl::eval_if< + apply_offset_filter, + result_of::advance_c, + unroll_again< + Iter, + Pred, + n, + 4> > > > >::type type; + }; + + template + struct unrolled_find_if + { + typedef typename mpl::eval_if< + apply_filter, + mpl::identity, + mpl::eval_if< + apply_offset_filter, + result_of::advance_c, + mpl::eval_if< + apply_offset_filter, + result_of::advance_c, + result_of::advance_c > > >::type type; + }; + + template + struct unrolled_find_if + { + typedef typename mpl::eval_if< + apply_filter, + mpl::identity, + mpl::eval_if< + apply_offset_filter, + result_of::advance_c, + result_of::advance_c > >::type type; + }; + + template + struct unrolled_find_if + { + typedef typename mpl::eval_if< + apply_filter, + mpl::identity, + result_of::advance_c >::type type; + }; + + template + struct unroll_again + { + typedef typename unrolled_find_if< + typename result_of::advance_c::type, + Pred, + n-unrolling>::type type; + }; + + template + struct unrolled_find_if + { + typedef Iter type; + }; + + template + struct choose_find_if + { + typedef typename result_of::distance::type N; + typedef typename unrolled_find_if::type type; + }; + template struct static_find_if { typedef typename - main_find_if< + choose_find_if< First , Last , typename mpl::lambda::type + , is_base_of::type>::value >::type type; template static type - call(Iterator const& iter, mpl::true_) + recursive_call(Iterator const& iter, mpl::true_) { return iter; } template static type - call(Iterator const& iter, mpl::false_) + recursive_call(Iterator const& iter, mpl::false_) { - return call(fusion::next(iter)); + return recursive_call(fusion::next(iter)); + } + + template + static type + recursive_call(Iterator const& iter) + { + typedef result_of::equal_to found; + return recursive_call(iter, found()); + } + + template + static type + choose_call(Iterator const& iter, Tag) + { + return recursive_call(iter); + } + + template + static type + choose_call(Iterator const& iter, random_access_traversal_tag) + { + typedef typename result_of::distance::type N; + return fusion::advance(iter); } template static type call(Iterator const& iter) { - typedef result_of::equal_to found; - return call(iter, found()); + return choose_call(iter, typename traits::category_of::type()); } };