#ifndef INCLUDE_GUARD_ADJACENT_DIFFERENCE_HH #define INCLUDE_GUARD_ADJACENT_DIFFERENCE_HH #include #include #include #include #include #include #include #include #include #include #include #include #include template ::value_type> > struct adjacent_difference_iterator : boost::iterator_adaptor< adjacent_difference_iterator, SinglePassIterator> { private: BOOST_CLASS_REQUIRE(SinglePassIterator, boost_concepts, SinglePassIteratorConcept); friend class boost::iterator_core_access; typename adjacent_difference_iterator::iterator_adaptor_::reference dereference() const { if (previous) { return binary_op(*this->base(), *previous); } else { return *this->base(); } } void increment() { previous = *this->base(); ++this->base_reference(); } boost::optional previous; BinaryFunction binary_op; public: adjacent_difference_iterator() { } explicit adjacent_difference_iterator(SinglePassIterator const &iterator) : adjacent_difference_iterator::iterator_adaptor_(iterator) { BOOST_STATIC_ASSERT(boost::is_class::value); } adjacent_difference_iterator(SinglePassIterator const &iterator, BinaryFunction binary_op) : adjacent_difference_iterator::iterator_adaptor_(iterator), binary_op(binary_op) { } BinaryFunction functor() const { return binary_op; } }; template adjacent_difference_iterator make_adjacent_difference_iterator(SinglePassIterator iterator) { return adjacent_difference_iterator(iterator); } template adjacent_difference_iterator make_adjacent_difference_iterator(SinglePassIterator iterator, BinaryFunction binary_op) { return adjacent_difference_iterator(iterator, binary_op); } template ::type> > struct adjacent_difference_range : boost::iterator_range::type, BinaryFunction> > { typedef typename boost::range_result_iterator::type base_iterator; typedef adjacent_difference_iterator iterator; typedef boost::iterator_range base_range; explicit adjacent_difference_range(SinglePassRange &range) : base_range( make_adjacent_difference_iterator(boost::begin(range)), make_adjacent_difference_iterator(boost::end(range))) { } adjacent_difference_range(SinglePassRange &range, BinaryFunction binary_op) : base_range( make_adjacent_difference_iterator(boost::begin(range), binary_op), make_adjacent_difference_iterator(boost::end(range), binary_op)) { } }; template adjacent_difference_range make_adjacent_difference_range(SinglePassRange &range) { return adjacent_difference_range(range); } template adjacent_difference_range make_adjacent_difference_range(SinglePassRange const &range) { return adjacent_difference_range(range); } template adjacent_difference_range make_adjacent_difference_range(SinglePassRange &range, BinaryFunction binary_op) { return adjacent_difference_range(range, binary_op); } template adjacent_difference_range make_adjacent_difference_range(SinglePassRange const &range, BinaryFunction binary_op) { return adjacent_difference_range(range, binary_op); } namespace detail { template struct adjacent_difference_range_adaptor_overload; template <> struct adjacent_difference_range_adaptor_overload<0> { template struct apply { BOOST_STATIC_ASSERT((boost::tuples::length::value == 0)); typedef adjacent_difference_range type; }; template static typename apply::type make_range(Range &range, Args const &args) { return make_adjacent_difference_range(range); } }; template <> struct adjacent_difference_range_adaptor_overload<1> { template struct apply { BOOST_STATIC_ASSERT((boost::tuples::length::value == 1)); typedef adjacent_difference_range::type> type; }; template static typename apply::type make_range(Range &range, Args const &args) { return make_adjacent_difference_range(range, boost::tuples::get<0>(args)); } }; struct adjacent_difference_range_adaptor { template struct apply { typedef typename adjacent_difference_range_adaptor_overload< boost::tuples::length::value>::template apply::type type; }; template static typename apply::type make_range(Range &range, Args const &args) { return adjacent_difference_range_adaptor_overload< boost::tuples::length::value>::make_range(range, args); } }; } // namespace detail boost::range_adaptor const adjacent_difference; #endif // !INCLUDE_GUARD_ADJACENT_DIFFERENCE_HH