From 4a80ccd50d1348d602297c93d2f19fcf103a519d Mon Sep 17 00:00:00 2001 From: Neil Groves Date: Sun, 1 Feb 2015 19:05:58 +0000 Subject: [PATCH] Ticket 10988 - Filtered adaptor should only require SinglePassRange. --- doc/reference/adaptors/filtered.qbk | 4 +- include/boost/range/adaptor/filtered.hpp | 51 ++++++++++--------- test/Jamfile.v2 | 4 -- test/adaptor_test/filtered.cpp | 24 +++++++++ .../compile_fail/adaptor/filtered_concept.cpp | 38 -------------- .../adaptor/filtered_concept2.cpp | 38 -------------- .../adaptor/filtered_concept3.cpp | 38 -------------- .../adaptor/filtered_concept4.cpp | 38 -------------- 8 files changed, 53 insertions(+), 182 deletions(-) delete mode 100644 test/compile_fail/adaptor/filtered_concept.cpp delete mode 100644 test/compile_fail/adaptor/filtered_concept2.cpp delete mode 100644 test/compile_fail/adaptor/filtered_concept3.cpp delete mode 100644 test/compile_fail/adaptor/filtered_concept4.cpp diff --git a/doc/reference/adaptors/filtered.qbk b/doc/reference/adaptors/filtered.qbk index 0340ed1..4ca3f91 100644 --- a/doc/reference/adaptors/filtered.qbk +++ b/doc/reference/adaptors/filtered.qbk @@ -12,9 +12,9 @@ ] * [*Precondition:] The `value_type` of the range is convertible to the argument type of `pred`. -* [*Postcondition:] For all adjacent elements `[x]` in the returned range, `pred(x)` is `true`. +* [*Postcondition:] For all elements `[x]` in the returned range, `pred(x)` is `true`. * [*Throws:] Whatever the copy constructor of `pred` might throw. -* [*Range Category:] __forward_range__ +* [*Range Category:] __singlepass_range__ * [*Range Return Type:] `boost::filtered_range` * [*Returned Range Category:] The minimum of the range category of `rng` and __bidirectional_range__ diff --git a/include/boost/range/adaptor/filtered.hpp b/include/boost/range/adaptor/filtered.hpp index b6d3ab1..1fb778e 100644 --- a/include/boost/range/adaptor/filtered.hpp +++ b/include/boost/range/adaptor/filtered.hpp @@ -56,23 +56,23 @@ namespace boost { } }; - template< class ForwardRange, class Predicate > - inline filtered_range - operator|(ForwardRange& r, + template< class SinglePassRange, class Predicate > + inline filtered_range + operator|(SinglePassRange& r, const filter_holder& f) { - BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - return filtered_range( f.val, r ); + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + return filtered_range( f.val, r ); } - template< class ForwardRange, class Predicate > - inline filtered_range - operator|(const ForwardRange& r, + template< class SinglePassRange, class Predicate > + inline filtered_range + operator|(const SinglePassRange& r, const filter_holder& f ) { BOOST_RANGE_CONCEPT_ASSERT(( - ForwardRangeConcept)); - return filtered_range( f.val, r ); + SinglePassRangeConcept)); + return filtered_range( f.val, r ); } } // 'range_detail' @@ -93,23 +93,26 @@ namespace boost range_detail::forwarder(); } - template - inline filtered_range - filter(ForwardRange& rng, Predicate filter_pred) - { - BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - - return range_detail::filtered_range( filter_pred, rng ); - } - - template - inline filtered_range - filter(const ForwardRange& rng, Predicate filter_pred) + template + inline filtered_range + filter(SinglePassRange& rng, Predicate filter_pred) { BOOST_RANGE_CONCEPT_ASSERT(( - ForwardRangeConcept)); + SinglePassRangeConcept)); - return range_detail::filtered_range( filter_pred, rng ); + return range_detail::filtered_range< + Predicate, SinglePassRange>( filter_pred, rng ); + } + + template + inline filtered_range + filter(const SinglePassRange& rng, Predicate filter_pred) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return range_detail::filtered_range< + Predicate, const SinglePassRange>( filter_pred, rng ); } } // 'adaptors' diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 0fa1fa6..05937c7 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -40,10 +40,6 @@ test-suite range : [ compile-fail compile_fail/adaptor/copied_concept2.cpp ] [ compile-fail compile_fail/adaptor/copied_concept3.cpp ] [ compile-fail compile_fail/adaptor/copied_concept4.cpp ] - [ compile-fail compile_fail/adaptor/filtered_concept.cpp ] - [ compile-fail compile_fail/adaptor/filtered_concept2.cpp ] - [ compile-fail compile_fail/adaptor/filtered_concept3.cpp ] - [ compile-fail compile_fail/adaptor/filtered_concept4.cpp ] [ compile-fail compile_fail/adaptor/reversed_concept.cpp ] [ compile-fail compile_fail/adaptor/reversed_concept2.cpp ] [ compile-fail compile_fail/adaptor/reversed_concept3.cpp ] diff --git a/test/adaptor_test/filtered.cpp b/test/adaptor_test/filtered.cpp index 8e7b958..17a457f 100644 --- a/test/adaptor_test/filtered.cpp +++ b/test/adaptor_test/filtered.cpp @@ -21,6 +21,7 @@ #include #include #include +#include namespace boost { @@ -113,12 +114,35 @@ namespace boost filtered_test_impl< Container, is_even >(); } + void ticket_10988_single_pass() + { + std::vector v; + std::string str("0 1 2 3 4 5"); + std::istringstream in(str); + + boost::push_back(v, + boost::make_iterator_range( + std::istream_iterator(in), + std::istream_iterator()) + | boost::adaptors::filtered(is_even())); + + std::vector reference; + for (int i = 0; i < 6; i += 2) + { + reference.push_back(i); + } + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + v.begin(), v.end()); + } + void filtered_test() { filtered_test_all_predicates< std::vector< int > >(); filtered_test_all_predicates< std::list< int > >(); filtered_test_all_predicates< std::set< int > >(); filtered_test_all_predicates< std::multiset< int > >(); + ticket_10988_single_pass(); } } } diff --git a/test/compile_fail/adaptor/filtered_concept.cpp b/test/compile_fail/adaptor/filtered_concept.cpp deleted file mode 100644 index 4242d3c..0000000 --- a/test/compile_fail/adaptor/filtered_concept.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Boost.Range library -// -// Copyright Neil Groves 2014. Use, modification and distribution is subject -// to 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) -// -// For more information, see http://www.boost.org/libs/range -// - -#include "mock_range.hpp" -#include - -namespace -{ - -struct always_true -{ - typedef bool result_type; - - bool operator()(int) const - { - return true; - } -}; - -} // anonymous namespace - -int main(int, const char**) -{ - using boost::range::unit_test::mock_range; - using boost::adaptors::filtered; - - // This next line should fail when Boost.Range concept checking is - // enabled since the filtered adaptor takes at least a ForwardRange. - return (mock_range() | - filtered(always_true())).front(); -} diff --git a/test/compile_fail/adaptor/filtered_concept2.cpp b/test/compile_fail/adaptor/filtered_concept2.cpp deleted file mode 100644 index d184eb0..0000000 --- a/test/compile_fail/adaptor/filtered_concept2.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Boost.Range library -// -// Copyright Neil Groves 2014. Use, modification and distribution is subject -// to 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) -// -// For more information, see http://www.boost.org/libs/range -// - -#include "mock_range.hpp" -#include - -namespace -{ - -struct always_true -{ - typedef bool result_type; - - bool operator()(int) const - { - return true; - } -}; - -} // anonymous namespace - -int main(int, const char**) -{ - using boost::range::unit_test::mock_const_range; - using boost::adaptors::filtered; - - // This next line should fail when Boost.Range concept checking is - // enabled since the filtered adaptor takes at least a ForwardRange. - return (mock_const_range() | - filtered(always_true())).front(); -} diff --git a/test/compile_fail/adaptor/filtered_concept3.cpp b/test/compile_fail/adaptor/filtered_concept3.cpp deleted file mode 100644 index 6a30185..0000000 --- a/test/compile_fail/adaptor/filtered_concept3.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Boost.Range library -// -// Copyright Neil Groves 2014. Use, modification and distribution is subject -// to 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) -// -// For more information, see http://www.boost.org/libs/range -// - -#include "mock_range.hpp" -#include - -namespace -{ - -struct always_true -{ - typedef bool result_type; - - bool operator()(int) const - { - return true; - } -}; - -} // anonymous namespace - -int main(int, const char**) -{ - using boost::range::unit_test::mock_range; - - // This next line should fail when Boost.Range concept checking is - // enabled since the filtered adaptor takes at least a ForwardRange. - return boost::adaptors::filter( - mock_range(), - always_true()).front(); -} diff --git a/test/compile_fail/adaptor/filtered_concept4.cpp b/test/compile_fail/adaptor/filtered_concept4.cpp deleted file mode 100644 index 8d21bba..0000000 --- a/test/compile_fail/adaptor/filtered_concept4.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Boost.Range library -// -// Copyright Neil Groves 2014. Use, modification and distribution is subject -// to 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) -// -// For more information, see http://www.boost.org/libs/range -// - -#include "mock_range.hpp" -#include - -namespace -{ - -struct always_true -{ - typedef bool result_type; - - bool operator()(int) const - { - return true; - } -}; - -} // anonymous namespace - -int main(int, const char**) -{ - using boost::range::unit_test::mock_const_range; - - // This next line should fail when Boost.Range concept checking is - // enabled since the filtered adaptor takes at least a ForwardRange. - return boost::adaptors::filter( - mock_const_range(), - always_true()).front(); -}