From fd0f99c767086447657f662a11faec2969401cca Mon Sep 17 00:00:00 2001 From: Neil Groves Date: Thu, 27 Feb 2014 13:51:06 +0000 Subject: [PATCH] inner_product avoids pre-condition check with input_iterators due to single-pass limitation. --- include/boost/range/numeric.hpp | 38 +++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/include/boost/range/numeric.hpp b/include/boost/range/numeric.hpp index c70069f..0b61527 100644 --- a/include/boost/range/numeric.hpp +++ b/include/boost/range/numeric.hpp @@ -30,8 +30,10 @@ #include #include #include +#include #include #include +#include #include @@ -51,13 +53,41 @@ namespace boost return std::accumulate( boost::begin(rng), boost::end(rng), init, op ); } + namespace range_detail + { + template + inline bool inner_product_precondition( + const SinglePassRange1&, + const SinglePassRange2&, + std::input_iterator_tag, + std::input_iterator_tag) + { + return true; + } + + template + inline bool inner_product_precondition( + const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + std::forward_iterator_tag, + std::forward_iterator_tag) + { + return boost::size(rng2) >= boost::size(rng1); + } + + } // namespace range_detail template< class SinglePassRange1, class SinglePassRange2, class Value > inline Value inner_product( const SinglePassRange1& rng1, const SinglePassRange2& rng2, Value init ) { BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_ASSERT( boost::distance(rng2) >= boost::distance(rng1) ); + BOOST_ASSERT( + range_detail::inner_product_precondition( + rng1, rng2, + typename range_category::type(), + typename range_category::type())); + return std::inner_product( boost::begin(rng1), boost::end(rng1), boost::begin(rng2), init ); } @@ -72,7 +102,11 @@ namespace boost { BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_ASSERT( boost::distance(rng2) >= boost::distance(rng1) ); + BOOST_ASSERT( + range_detail::inner_product_precondition( + rng1, rng2, + typename range_category::type(), + typename range_category::type())); return std::inner_product( boost::begin(rng1), boost::end(rng1), boost::begin(rng2), init, op1, op2 );