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/include/boost/range/adaptor/strided.hpp b/include/boost/range/adaptor/strided.hpp index c5fea86..560b820 100644 --- a/include/boost/range/adaptor/strided.hpp +++ b/include/boost/range/adaptor/strided.hpp @@ -603,7 +603,7 @@ namespace boost template< class Rng, class Category = - typename iterator_traversal< + typename iterators::pure_iterator_traversal< typename range_iterator::type >::type > diff --git a/include/boost/range/detail/common.hpp b/include/boost/range/detail/common.hpp index b0ad535..00b665b 100644 --- a/include/boost/range/detail/common.hpp +++ b/include/boost/range/detail/common.hpp @@ -18,9 +18,10 @@ #include #include #include -#include +#include #include #include +#include #include ////////////////////////////////////////////////////////////////////////////// @@ -70,7 +71,7 @@ namespace boost BOOST_STATIC_CONSTANT( bool, is_const_wchar_t_ptr_ = sizeof( boost::range_detail::is_const_wchar_t_ptr_impl( ptr ) ) == sizeof( yes_type ) ); BOOST_STATIC_CONSTANT( bool, is_char_array_ = sizeof( boost::range_detail::is_char_array_impl( ptr ) ) == sizeof( yes_type ) ); BOOST_STATIC_CONSTANT( bool, is_wchar_t_array_ = sizeof( boost::range_detail::is_wchar_t_array_impl( ptr ) ) == sizeof( yes_type ) ); - BOOST_STATIC_CONSTANT( bool, is_string_ = (boost::type_traits::ice_or::value )); + BOOST_STATIC_CONSTANT( bool, is_string_ = (boost::mpl::or_, boost::mpl::bool_ >::value )); BOOST_STATIC_CONSTANT( bool, is_array_ = boost::is_array::value ); }; diff --git a/include/boost/range/difference_type.hpp b/include/boost/range/difference_type.hpp index afd8b07..6bb3c5f 100644 --- a/include/boost/range/difference_type.hpp +++ b/include/boost/range/difference_type.hpp @@ -15,20 +15,32 @@ # pragma once #endif +#include #include #include +#include #include #include namespace boost { + namespace range_detail + { + template< class T, bool B = has_type >::value > + struct range_difference + { }; + + template< class T > + struct range_difference + : iterator_difference< + BOOST_DEDUCED_TYPENAME range_iterator::type + > + { }; + } + template< class T > struct range_difference - : iterator_difference< - BOOST_DEDUCED_TYPENAME range_iterator< - BOOST_DEDUCED_TYPENAME remove_reference::type - >::type - > + : range_detail::range_difference::type> { }; } diff --git a/include/boost/range/iterator.hpp b/include/boost/range/iterator.hpp index f15bf3b..2956353 100644 --- a/include/boost/range/iterator.hpp +++ b/include/boost/range/iterator.hpp @@ -46,31 +46,29 @@ namespace boost }; } -#endif - template< typename C, typename Enabler=void > struct range_iterator { -#if BOOST_WORKAROUND(BOOST_MSVC, == 1310) - + typedef BOOST_RANGE_DEDUCED_TYPENAME range_detail_vc7_1::range_iterator::type type; - -#else - private: - typedef typename remove_reference::type param_t; - - public: - typedef typename mpl::eval_if_c< - is_const::value, - range_const_iterator::type>, - range_mutable_iterator - >::type type; - -#endif }; - + +#else + + template< typename C, typename Enabler=void > + struct range_iterator + : mpl::if_c< + is_const::type>::value, + range_const_iterator::type>::type>, + range_mutable_iterator::type> + >::type + { + }; + +#endif + } // namespace boost #endif diff --git a/include/boost/range/iterator_range_core.hpp b/include/boost/range/iterator_range_core.hpp index 2fbeb68..a9e9fc0 100644 --- a/include/boost/range/iterator_range_core.hpp +++ b/include/boost/range/iterator_range_core.hpp @@ -66,13 +66,13 @@ namespace boost template< class ForwardRange > static IteratorT adl_begin( ForwardRange& r ) { - return static_cast( boost::begin( r ) ); + return IteratorT( boost::begin( r ) ); } template< class ForwardRange > static IteratorT adl_end( ForwardRange& r ) { - return static_cast( boost::end( r ) ); + return IteratorT( boost::end( r ) ); } }; diff --git a/include/boost/range/size.hpp b/include/boost/range/size.hpp index d007bfc..7f38db8 100644 --- a/include/boost/range/size.hpp +++ b/include/boost/range/size.hpp @@ -54,11 +54,20 @@ namespace boost inline typename range_size::type size(const SinglePassRange& rng) { +// Very strange things happen on some compilers that have the range concept +// asserts disabled. This preprocessor condition is clearly redundant on a +// working compiler but is vital for at least some compilers such as clang 4.2 +// but only on the Mac! +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT == 1 + BOOST_RANGE_CONCEPT_ASSERT((boost::SinglePassRangeConcept)); +#endif + #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \ !BOOST_WORKAROUND(__GNUC__, < 3) \ /**/ using namespace range_detail; #endif + return range_calculate_size(rng); } diff --git a/include/boost/range/size_type.hpp b/include/boost/range/size_type.hpp index db5a59b..f41c321 100644 --- a/include/boost/range/size_type.hpp +++ b/include/boost/range/size_type.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -51,7 +52,7 @@ namespace boost }; template - struct range_size + struct range_size_ { typedef BOOST_DEDUCED_TYPENAME make_unsigned< BOOST_DEDUCED_TYPENAME range_difference::type @@ -59,7 +60,7 @@ namespace boost }; template - struct range_size< + struct range_size_< C, BOOST_DEDUCED_TYPENAME ::boost::enable_if, void>::type > @@ -67,29 +68,25 @@ namespace boost typedef BOOST_DEDUCED_TYPENAME C::size_type type; }; + template >::value> + struct range_size + { }; + + template + struct range_size + : range_size_ + { }; } template< class T > struct range_size : detail::range_size - { -// Very strange things happen on some compilers that have the range concept -// asserts disabled. This preprocessor condition is clearly redundant on a -// working compiler but is vital for at least some compilers such as clang 4.2 -// but only on the Mac! -#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT == 1 - BOOST_RANGE_CONCEPT_ASSERT((boost::SinglePassRangeConcept)); -#endif - }; + { }; template< class T > - struct range_size - : detail::range_size - { -#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT == 1 - BOOST_RANGE_CONCEPT_ASSERT((boost::SinglePassRangeConcept)); -#endif - }; + struct range_size : + detail::range_size + { }; } // namespace boost diff --git a/include/boost/range/sub_range.hpp b/include/boost/range/sub_range.hpp index 8d5d168..d1c3b99 100644 --- a/include/boost/range/sub_range.hpp +++ b/include/boost/range/sub_range.hpp @@ -182,8 +182,8 @@ public: #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500) ) sub_range(const sub_range& r) - : base(impl::adl_begin(static_cast(r)), - impl::adl_end(static_cast(r))) + : base(impl::adl_begin(const_cast(static_cast(r))), + impl::adl_end(const_cast(static_cast(r)))) { } #endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index dcc20c6..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 ] @@ -219,6 +215,7 @@ test-suite range : [ range-test ticket_5811_indirected_optional ] [ range-test ticket_6715_iterator_range_equality ] [ range-test ticket_6944 ] + [ range-test ticket_10336 ] [ range-test value_type ] ; 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(); -} diff --git a/test/sub_range.cpp b/test/sub_range.cpp index be48811..a6dbb36 100644 --- a/test/sub_range.cpp +++ b/test/sub_range.cpp @@ -244,6 +244,22 @@ inline void test_advance() BOOST_CHECK_EQUAL(r3.advance_end(-1).size(), 1u); } +void ticket_10514() +{ + typedef std::vector vec_t; + typedef boost::sub_range range_t; + vec_t v(10); + range_t r(v.begin(), v.end()); + const range_t& cr = r; + range_t copy_r = cr; + + BOOST_CHECK(r.begin() == copy_r.begin()); + BOOST_CHECK(r.end() == copy_r.end()); + + BOOST_CHECK(cr.begin() == copy_r.begin()); + BOOST_CHECK(cr.end() == copy_r.end()); +} + } // anonymous namespace } // namespace boost_range_test @@ -262,6 +278,8 @@ boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) test->add(BOOST_TEST_CASE(&boost_range_test::test_advance)); + test->add(BOOST_TEST_CASE(&boost_range_test::ticket_10514)); + return test; } diff --git a/test/ticket_10336.cpp b/test/ticket_10336.cpp new file mode 100644 index 0000000..541e037 --- /dev/null +++ b/test/ticket_10336.cpp @@ -0,0 +1,43 @@ +// Boost.Range library +// +// Copyright Neil Groves 2011. 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 +#include + +#include +#include + +namespace boost +{ + namespace + { + // Ticket 10336 - compilation error in iterator_range and unordered_map + void test_ticket_10336() + { + typedef boost::unordered_map container_t; + typedef container_t::const_iterator citer_t; + typedef boost::iterator_range rng_t; + + const container_t c; + rng_t rng(c.begin(), c.end()); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.ticket_10336" ); + + test->add( BOOST_TEST_CASE( &boost::test_ticket_10336 ) ); + + return test; +}