From fd0f99c767086447657f662a11faec2969401cca Mon Sep 17 00:00:00 2001 From: Neil Groves Date: Thu, 27 Feb 2014 13:51:06 +0000 Subject: [PATCH 1/3] 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 ); From 9b477525de9e1f38431ea18c32ec98590d45724d Mon Sep 17 00:00:00 2001 From: Neil Groves Date: Thu, 27 Feb 2014 15:59:03 +0000 Subject: [PATCH 2/3] reformatted numeric.hpp --- include/boost/range/numeric.hpp | 150 ++++++++++++++++++++------------ 1 file changed, 93 insertions(+), 57 deletions(-) diff --git a/include/boost/range/numeric.hpp b/include/boost/range/numeric.hpp index 0b61527..d1510cd 100644 --- a/include/boost/range/numeric.hpp +++ b/include/boost/range/numeric.hpp @@ -1,14 +1,8 @@ -/////////////////////////////////////////////////////////////////////////////// -/// \file algorithm.hpp -/// Contains range-based versions of the std algorithms -// -///////////////////////////////////////////////////////////////////////////// -// Copyright 2009 Neil Groves. +// Copyright 2009-2014 Neil Groves. // 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) // - // Copyright 2006 Thorsten Ottosen. // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -18,7 +12,9 @@ // 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) - +// +// Contains range-based versions of the numeric std algorithms +// #if defined(_MSC_VER) #pragma once #endif @@ -39,18 +35,23 @@ namespace boost { - template< class SinglePassRange, class Value > - inline Value accumulate( const SinglePassRange& rng, Value init ) + template + inline Value accumulate(const SinglePassRange& rng, Value init) { - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::accumulate( boost::begin(rng), boost::end(rng), init ); + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return std::accumulate(boost::begin(rng), boost::end(rng), init); } - template< class SinglePassRange, class Value, class BinaryOperation > - inline Value accumulate( const SinglePassRange& rng, Value init, BinaryOperation op ) + template + inline Value accumulate(const SinglePassRange& rng, Value init, + BinaryOperation op) { - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::accumulate( boost::begin(rng), boost::end(rng), init, op ); + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept )); + + return std::accumulate(boost::begin(rng), boost::end(rng), init, op); } namespace range_detail @@ -77,76 +78,111 @@ namespace boost } // namespace range_detail - template< class SinglePassRange1, class SinglePassRange2, class Value > - inline Value inner_product( const SinglePassRange1& rng1, const SinglePassRange2& rng2, Value init ) + 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_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + 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 ); + return std::inner_product( + boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), init); } - template< class SinglePassRange1, - class SinglePassRange2, - class Value, - class BinaryOperation1, class BinaryOperation2 > - inline Value inner_product( const SinglePassRange1& rng1, const SinglePassRange2& rng2, - Value init, - BinaryOperation1 op1, BinaryOperation2 op2 ) + template< + class SinglePassRange1, + class SinglePassRange2, + class Value, + class BinaryOperation1, + class BinaryOperation2 + > + inline Value inner_product( + const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + Value init, + BinaryOperation1 op1, + BinaryOperation2 op2) { - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + 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 ); + return std::inner_product( + boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), init, op1, op2); } - template< class SinglePassRange, class OutputIterator > - inline OutputIterator partial_sum ( const SinglePassRange& rng, - OutputIterator result ) + template + inline OutputIterator partial_sum(const SinglePassRange& rng, + OutputIterator result) { - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::partial_sum( boost::begin(rng), boost::end(rng), result ); + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return std::partial_sum(boost::begin(rng), boost::end(rng), result); } - template< class SinglePassRange, class OutputIterator, class BinaryOperation > - inline OutputIterator partial_sum ( const SinglePassRange& rng, OutputIterator result, - BinaryOperation op ) + template + inline OutputIterator partial_sum( + const SinglePassRange& rng, + OutputIterator result, + BinaryOperation op) { - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::partial_sum( boost::begin(rng), boost::end(rng), result, op ); + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return std::partial_sum(boost::begin(rng), boost::end(rng), result, op); } - template< class SinglePassRange, class OutputIterator > - inline OutputIterator adjacent_difference ( const SinglePassRange& rng, - OutputIterator result ) + template + inline OutputIterator adjacent_difference( + const SinglePassRange& rng, + OutputIterator result) { - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::adjacent_difference( boost::begin(rng), boost::end(rng), - result ); + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return std::adjacent_difference(boost::begin(rng), boost::end(rng), + result); } - template< class SinglePassRange, class OutputIterator, class BinaryOperation > - inline OutputIterator adjacent_difference ( const SinglePassRange& rng, - OutputIterator result, - BinaryOperation op ) + template + inline OutputIterator adjacent_difference( + const SinglePassRange& rng, + OutputIterator result, + BinaryOperation op) { - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::adjacent_difference( boost::begin(rng), boost::end(rng), - result, op ); + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return std::adjacent_difference(boost::begin(rng), boost::end(rng), + result, op); } -} +} // namespace boost #endif From 502abb988420f0e28dca329e77bcdf9143af5d77 Mon Sep 17 00:00:00 2001 From: Neil Groves Date: Thu, 27 Feb 2014 16:34:58 +0000 Subject: [PATCH 3/3] eliminate unused local typedef and signed/unsigned comparison warnings. --- test/algorithm.cpp | 13 ++++++++----- test/algorithm_test/inplace_merge.cpp | 7 +++++-- test/algorithm_test/max_element.cpp | 7 +++++-- test/algorithm_test/min_element.cpp | 7 +++++-- test/algorithm_test/mismatch.cpp | 18 ++++++++++-------- test/algorithm_test/random_shuffle.cpp | 3 ++- test/algorithm_test/remove_copy.cpp | 3 ++- test/algorithm_test/replace_copy.cpp | 3 ++- test/algorithm_test/rotate_copy.cpp | 7 +++++-- test/algorithm_test/search_n.cpp | 4 +++- test/compat3.cpp | 2 ++ test/iterator_pair.cpp | 14 ++++++++++---- 12 files changed, 59 insertions(+), 29 deletions(-) diff --git a/test/algorithm.cpp b/test/algorithm.cpp index 2160eaf..ebe0496 100644 --- a/test/algorithm.cpp +++ b/test/algorithm.cpp @@ -107,12 +107,15 @@ template void test_random_algorithms(Rng & rng, std::random_access_iterator_tag) { typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iterator; - typedef BOOST_DEDUCED_TYPENAME boost::range_value::type value_type; - typedef BOOST_DEDUCED_TYPENAME boost::range_size::type size_type BOOST_RANGE_UNUSED; - typedef BOOST_DEDUCED_TYPENAME boost::iterator_category::type iterator_category; - - + typedef BOOST_DEDUCED_TYPENAME boost::range_value::type value_type; + + typedef BOOST_DEDUCED_TYPENAME boost::range_size::type + size_type BOOST_RANGE_UNUSED; + + typedef BOOST_DEDUCED_TYPENAME boost::iterator_category::type + iterator_category BOOST_RANGE_UNUSED; + // just make sure these compile (for now) if(0) { diff --git a/test/algorithm_test/inplace_merge.cpp b/test/algorithm_test/inplace_merge.cpp index d0cad73..948e95e 100644 --- a/test/algorithm_test/inplace_merge.cpp +++ b/test/algorithm_test/inplace_merge.cpp @@ -28,7 +28,9 @@ namespace boost void test(Container1& cont1, Container2& cont2) { typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t; - typedef BOOST_DEDUCED_TYPENAME std::vector::iterator iterator_t; + + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator + iterator_t BOOST_RANGE_UNUSED; std::vector reference_target(cont1.begin(), cont1.end()); reference_target.insert(reference_target.end(), @@ -74,7 +76,8 @@ namespace boost void test_pred(Container1 cont1, Container2 cont2, BinaryPredicate pred) { typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t; - typedef BOOST_DEDUCED_TYPENAME std::vector::iterator iterator_t; + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator + iterator_t BOOST_RANGE_UNUSED; sort_container(cont1, pred); sort_container(cont2, pred); diff --git a/test/algorithm_test/max_element.cpp b/test/algorithm_test/max_element.cpp index 9a26099..d4e87d5 100644 --- a/test/algorithm_test/max_element.cpp +++ b/test/algorithm_test/max_element.cpp @@ -106,8 +106,11 @@ namespace boost_range_test_algorithm_max_element { using namespace boost::assign; - typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; - typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type container_t; + typedef BOOST_DEDUCED_TYPENAME Container::value_type + value_t BOOST_RANGE_UNUSED; + + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type + container_t; boost::range_test::range_return_test_driver test_driver; diff --git a/test/algorithm_test/min_element.cpp b/test/algorithm_test/min_element.cpp index 0f9fa68..bb92d2c 100644 --- a/test/algorithm_test/min_element.cpp +++ b/test/algorithm_test/min_element.cpp @@ -104,8 +104,11 @@ namespace boost_range_test_algorithm_min_element { using namespace boost::assign; - typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; - typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type container_t; + typedef BOOST_DEDUCED_TYPENAME Container::value_type + value_t BOOST_RANGE_UNUSED; + + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type + container_t; boost::range_test::range_return_test_driver test_driver; diff --git a/test/algorithm_test/mismatch.cpp b/test/algorithm_test/mismatch.cpp index 2336e59..407b5fc 100644 --- a/test/algorithm_test/mismatch.cpp +++ b/test/algorithm_test/mismatch.cpp @@ -160,15 +160,17 @@ namespace boost MutableContainer2 cont2; const Container2& cref_cont2 = cont2; - typedef BOOST_DEDUCED_TYPENAME Container1::iterator iterator1_t; - typedef BOOST_DEDUCED_TYPENAME Container1::const_iterator const_iterator1_t; - typedef BOOST_DEDUCED_TYPENAME Container2::iterator iterator2_t; - typedef BOOST_DEDUCED_TYPENAME Container2::const_iterator const_iterator2_t; + typedef BOOST_DEDUCED_TYPENAME Container1::iterator + iterator1_t BOOST_RANGE_UNUSED; - typedef std::pair pair_mmit_t; - typedef std::pair pair_cmit_t; - typedef std::pair pair_mcit_t; - typedef std::pair pair_ccit_t; + typedef BOOST_DEDUCED_TYPENAME Container1::const_iterator + const_iterator1_t BOOST_RANGE_UNUSED; + + typedef BOOST_DEDUCED_TYPENAME Container2::iterator + iterator2_t BOOST_RANGE_UNUSED; + + typedef BOOST_DEDUCED_TYPENAME Container2::const_iterator + const_iterator2_t BOOST_RANGE_UNUSED; eval_mismatch(cont1, cont2, cont1.end(), cont2.end()); eval_mismatch(cont1, cont2, std::equal_to(), cont1.end(), cont2.end()); diff --git a/test/algorithm_test/random_shuffle.cpp b/test/algorithm_test/random_shuffle.cpp index 410749a..71915ee 100644 --- a/test/algorithm_test/random_shuffle.cpp +++ b/test/algorithm_test/random_shuffle.cpp @@ -90,7 +90,8 @@ namespace boost template void test_random_shuffle_nogen_impl(Container& cont) { - typedef BOOST_DEDUCED_TYPENAME range_iterator::type iterator_t; + typedef BOOST_DEDUCED_TYPENAME range_iterator::type + iterator_t BOOST_RANGE_UNUSED; const int MAX_RETRIES = 10000; diff --git a/test/algorithm_test/remove_copy.cpp b/test/algorithm_test/remove_copy.cpp index 4050ef4..b3eb8e2 100644 --- a/test/algorithm_test/remove_copy.cpp +++ b/test/algorithm_test/remove_copy.cpp @@ -36,7 +36,8 @@ namespace typedef typename boost::range_value::type value_type; std::vector reference; - typedef BOOST_DEDUCED_TYPENAME std::vector::iterator iterator_t; + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator + iterator_t BOOST_RANGE_UNUSED; test_append( std::remove_copy(c.begin(), c.end(), diff --git a/test/algorithm_test/replace_copy.cpp b/test/algorithm_test/replace_copy.cpp index 6ae12e2..5629856 100644 --- a/test/algorithm_test/replace_copy.cpp +++ b/test/algorithm_test/replace_copy.cpp @@ -38,7 +38,8 @@ namespace typedef typename boost::range_value::type value_type; std::vector reference; - typedef BOOST_DEDUCED_TYPENAME std::vector::iterator iterator_t; + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator + iterator_t BOOST_RANGE_UNUSED; test_append( std::replace_copy(c.begin(), c.end(), diff --git a/test/algorithm_test/rotate_copy.cpp b/test/algorithm_test/rotate_copy.cpp index 5615479..05aa4d2 100644 --- a/test/algorithm_test/rotate_copy.cpp +++ b/test/algorithm_test/rotate_copy.cpp @@ -31,11 +31,14 @@ namespace template void test_rotate_copy_impl(Container& cont, Iterator where_it) { - typedef BOOST_DEDUCED_TYPENAME boost::range_value::type value_type; + typedef BOOST_DEDUCED_TYPENAME boost::range_value::type + value_type; + std::vector reference; std::vector test; - typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iterator_t; + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type + iterator_t BOOST_RANGE_UNUSED; test_append( std::rotate_copy(cont.begin(), where_it, cont.end(), diff --git a/test/algorithm_test/search_n.cpp b/test/algorithm_test/search_n.cpp index 246d397..76f5b78 100644 --- a/test/algorithm_test/search_n.cpp +++ b/test/algorithm_test/search_n.cpp @@ -60,7 +60,9 @@ namespace Integer count, const Value& value, BinaryPredicate pred) { - typedef typename std::iterator_traits::iterator_category cat_t; + typedef typename std::iterator_traits< + ForwardIterator + >::iterator_category cat_t BOOST_RANGE_UNUSED; if (count <= 0) return first; diff --git a/test/compat3.cpp b/test/compat3.cpp index 5249c58..e4e4c83 100644 --- a/test/compat3.cpp +++ b/test/compat3.cpp @@ -10,6 +10,7 @@ #include #include +#include #include enum Container {}; @@ -51,6 +52,7 @@ void compat1() { std::vector v; iterator_of< std::vector >::type i = v.begin(); + boost::ignore_unused_variable_warning(i); } #include diff --git a/test/iterator_pair.cpp b/test/iterator_pair.cpp index 997b5fb..ba13d75 100644 --- a/test/iterator_pair.cpp +++ b/test/iterator_pair.cpp @@ -63,18 +63,24 @@ void check_iterator_pair() BOOST_CHECK( boost::begin( pair ) == pair.first ); BOOST_CHECK( boost::end( pair ) == pair.second ); BOOST_CHECK( boost::empty( pair ) == (pair.first == pair.second) ); - BOOST_CHECK( boost::size( pair ) == std::distance( pair.first, pair.second ) ); + BOOST_CHECK( boost::size( pair ) == + static_cast( + std::distance(pair.first, pair.second)) ); BOOST_CHECK( boost::begin( const_pair ) == const_pair.first ); BOOST_CHECK( boost::end( const_pair ) == const_pair.second ); BOOST_CHECK( boost::empty( const_pair ) == (const_pair.first == const_pair.second) ); - BOOST_CHECK( boost::size( const_pair ) == std::distance( const_pair.first, const_pair.second ) ); + BOOST_CHECK( boost::size( const_pair ) == + static_cast( + std::distance(const_pair.first, const_pair.second)) ); BOOST_CHECK( boost::begin( constness_pair ) == constness_pair.first ); BOOST_CHECK( boost::end( constness_pair ) == constness_pair.second ); BOOST_CHECK( boost::empty( constness_pair ) == (constness_pair.first == const_pair.second) ); - BOOST_CHECK( boost::size( constness_pair ) == std::distance( constness_pair.first, constness_pair.second ) ); - + BOOST_CHECK( boost::size( constness_pair ) == + static_cast( + std::distance(constness_pair.first, + constness_pair.second)) ); }