#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include template struct associated_range { typedef std::pair type; }; template bool range_empty(const T& range) { return(boost::empty(range)); } template bool increment_range_begin_and_test(T& range) { range = T(boost::next(boost::begin(range)), boost::end(range)); return(range_empty(range)); } template void increment_range_begin(T& range) { range = T(boost::next(boost::begin(range)), boost::end(range)); } template typename boost::range_reference::type range_front(T& range) { return(*boost::begin(range)); } template bool range_begin_equal(const T& lhs, const T& rhs) { return(boost::begin(lhs) == boost::begin(rhs)); } template class filter_range; template struct filter_iterator : boost::iterator_facade< filter_iterator, typename std::iterator_traits::value_type, std::forward_iterator_tag, typename std::iterator_traits::reference> { friend class boost::iterator_core_access; template friend class filter_range; filter_iterator(Iter b, Iter e, F f ) : m_range(b,e), m_f(f) {} private: void increment1() { while(!increment_range_begin_and_test(m_range) && !m_f(range_front(m_range))) {} } void increment2() { increment_range_begin(m_range); while(!range_empty(m_range) && !m_f(range_front(m_range))) { increment_range_begin(m_range); } } void increment() { increment2(); } reference dereference() const { return range_front(m_range); } bool equal(filter_iterator const& rhs) const { return range_begin_equal(m_range, rhs.m_range); } typename associated_range::type m_range; F m_f; // use compressed pair here }; template class filter_range { public: typedef filter_iterator::type, F> iterator; typedef filter_iterator::type, F> const_iterator; filter_range(iterator b, iterator e) : m_range(boost::begin(b.m_range), boost::begin(e.m_range)), m_f(b.m_f) {} filter_range(typename boost::range_iterator::type b, typename boost::range_iterator::type e, F f) : m_range(b, e), m_f(f) {} filter_range(R r, F f) : m_range(r), m_f(f) {} iterator begin() { return iterator(boost::begin(m_range), boost::end(m_range), m_f); } iterator end() { return iterator(boost::end(m_range), boost::end(m_range), m_f); } const_iterator begin() const { return const_iterator(boost::begin(m_range), boost::end(m_range), m_f); } const_iterator end() const { return const_iterator(boost::end(m_range), boost::end(m_range), m_f); } friend __forceinline bool increment_range_begin_and_test(filter_range& range) { while(true) { if(increment_range_begin_and_test(range.m_range)) { return(true); } else if(range.m_f(range_front(range.m_range))) { return(false); } } } friend __forceinline void increment_range_begin(filter_range& range) { increment_range_begin(range.m_range); while(!range_empty(range) && !range.m_f(range_front(range.m_range))) { increment_range_begin(range.m_range); } } friend bool range_empty(const filter_range& range) { return(range_empty(range.m_range)); } friend typename boost::range_reference::type range_front(filter_range& range) { return(range_front(range.m_range)); } friend typename boost::range_reference::type range_front(const filter_range& range) { return(range_front(range.m_range)); } bool range_begin_equal(const filter_range& lhs, const filter_range& rhs) { return(range_begin_equal(lhs.m_range, rhs.m_range)); } private: R m_range; F m_f; // use compressed pair }; // specialization template struct associated_range > { typedef filter_range::type, F> type; }; template struct is_not_divisible_by { bool operator()(int n) { return(n % N != 0); } }; struct make_filter_range { template struct result { typedef boost::function_traits traits; typedef typename traits::arg1_type arg1_type; typedef typename traits::arg2_type arg2_type; typedef filter_range< typename boost::remove_cv< typename boost::remove_reference::type >::type, typename boost::remove_cv< typename boost::remove_reference::type >::type > type; }; template typename result::type operator()(F f, Range range) { return(typename result::type(range, f)); } }; template unsigned sum(const Range& range) { return(std::accumulate(boost::begin(range), boost::end(range), 0u)); } volatile int force_calculation; int main() { std::vector data; std::srand(10); std::generate_n(std::back_inserter(data), 10000000, &std::rand); std::pair::const_iterator, std::vector::const_iterator> data_range(data.begin(), data.end()); { boost::timer timer; namespace fusion = boost::fusion; using boost::phoenix::arg_names::_1; int i = sum(fusion::fold(fusion::make_vector(_1 % 2 != 0, _1 % 3 != 0, _1 % 5 != 0, _1 % 7 != 0), data_range, make_filter_range())); std::cout << timer.elapsed() << " seconds\n"; force_calculation = i; std::cout << i << std::endl; } { boost::timer timer; namespace fusion = boost::fusion; using boost::phoenix::arg_names::_1; int i = sum(fusion::fold(fusion::make_vector(is_not_divisible_by<2>(), is_not_divisible_by<3>(), is_not_divisible_by<5>(), is_not_divisible_by<7>()), data_range, make_filter_range())); std::cout << timer.elapsed() << " seconds\n"; force_calculation = i; std::cout << i << std::endl; } { boost::timer timer; int i = 0; for(std::vector::const_iterator begin = data.begin(), end = data.end(); begin != end; ++begin) { if(*begin % 2 != 0 && *begin % 3 != 0 && *begin % 5 != 0 && *begin % 7 != 0) { i += *begin; } } std::cout << timer.elapsed() << " seconds\n"; force_calculation = i; std::cout << i << std::endl; } }