diff --git a/doc/reference/algorithm_ext/iota.qbk b/doc/reference/algorithm_ext/iota.qbk new file mode 100644 index 0000000..37aba15 --- /dev/null +++ b/doc/reference/algorithm_ext/iota.qbk @@ -0,0 +1,28 @@ +[section:for_each for_each] + +[heading Prototype] + +`` +template +iota(SinglePassRange& rng, Value x); +`` + +[heading Description] + +`iota` traverses forward through `rng`, each element `y` in `rng` is assigned a value equivalent +to `x + boost::distance(boost::begin(rng), it)` + +[heading Definition] + +Defined in the header file `boost/range/algorithm_ext/iota.hpp` + +[heading Requirements] + +# `SinglePassRange` is a model of the __single_pass_range__ Concept. +# `Value` is a model of the `Incrementable` Concept. + +[heading Complexity] + +Linear. Exactly `distance(rng)` assignments into `rng`. + +[endsect] diff --git a/doc/reference/algorithms.qbk b/doc/reference/algorithms.qbk index 9bbce12..00b3edb 100644 --- a/doc/reference/algorithms.qbk +++ b/doc/reference/algorithms.qbk @@ -144,6 +144,7 @@ and there is no need to worry about generating an invalid range. Furthermore, if [include algorithm_ext/erase.qbk] [include algorithm_ext/for_each.qbk] [include algorithm_ext/insert.qbk] +[include algorithm_ext/iota.qbk] [include algorithm_ext/overwrite.qbk] [include algorithm_ext/push_back.qbk] [include algorithm_ext/push_front.qbk] diff --git a/include/boost/range/algorithm/for_each.hpp b/include/boost/range/algorithm/for_each.hpp index cc65e6e..714a06f 100755 --- a/include/boost/range/algorithm/for_each.hpp +++ b/include/boost/range/algorithm/for_each.hpp @@ -35,10 +35,10 @@ inline UnaryFunction for_each(SinglePassRange & rng, UnaryFunction fun) /// \overload template< class SinglePassRange, class UnaryFunction > -inline UnaryFunction for_each(SinglePassRange const & rng, UnaryFunction fun) +inline UnaryFunction for_each(const SinglePassRange& rng, UnaryFunction fun) { BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::for_each(boost::begin(rng),boost::end(rng),fun); + return std::for_each(boost::begin(rng), boost::end(rng), fun); } } // namespace range diff --git a/include/boost/range/algorithm_ext.hpp b/include/boost/range/algorithm_ext.hpp index 002e791..783d38a 100755 --- a/include/boost/range/algorithm_ext.hpp +++ b/include/boost/range/algorithm_ext.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/include/boost/range/algorithm_ext/copy_n.hpp b/include/boost/range/algorithm_ext/copy_n.hpp index 39b7d3e..ba7ad1c 100755 --- a/include/boost/range/algorithm_ext/copy_n.hpp +++ b/include/boost/range/algorithm_ext/copy_n.hpp @@ -21,27 +21,33 @@ namespace boost { - /// \brief template function copy - /// - /// range-based version of the copy std algorithm - /// - /// \pre SinglePassRange is a model of the SinglePassRangeConcept - /// \pre OutputIterator is a model of the OutputIteratorConcept - /// \pre 0 <= n < distance(rng) - template< class SinglePassRange, class Size, class OutputIterator > - inline OutputIterator copy_n(const SinglePassRange& rng, Size n, OutputIterator out) + namespace range { - boost::function_requires< SinglePassRangeConcept >(); - BOOST_ASSERT( n < static_cast(boost::distance(rng)) ); - BOOST_ASSERT( n >= static_cast(0) ); - BOOST_DEDUCED_TYPENAME range_const_iterator::type source = boost::begin(rng); +/// \brief template function copy +/// +/// range-based version of the copy std algorithm +/// +/// \pre SinglePassRange is a model of the SinglePassRangeConcept +/// \pre OutputIterator is a model of the OutputIteratorConcept +/// \pre 0 <= n < distance(rng) +template< class SinglePassRange, class Size, class OutputIterator > +inline OutputIterator copy_n(const SinglePassRange& rng, Size n, OutputIterator out) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_ASSERT( n < static_cast(boost::distance(rng)) ); + BOOST_ASSERT( n >= static_cast(0) ); - for (Size i = 0; i < n; ++i, ++out, ++source) - *out = *source; + BOOST_DEDUCED_TYPENAME range_iterator::type source = boost::begin(rng); - return out; - } + for (Size i = 0; i < n; ++i, ++out, ++source) + *out = *source; + + return out; } + } // namespace range + using range::copy_n; +} // namespace boost + #endif // include guard diff --git a/include/boost/range/algorithm_ext/erase.hpp b/include/boost/range/algorithm_ext/erase.hpp index c57d14d..3b0e037 100755 --- a/include/boost/range/algorithm_ext/erase.hpp +++ b/include/boost/range/algorithm_ext/erase.hpp @@ -11,35 +11,48 @@ #define BOOST_RANGE_ALGORITHM_EXT_ERASE_HPP_INCLUDED #include +#include #include +#include #include #include #include namespace boost { - template< class Container > - inline void erase( Container& on, - iterator_range to_erase ) - { - on.erase( boost::begin(to_erase), boost::end(to_erase) ); - } + namespace range + { - template< class Container, class T > - inline void remove_erase( Container& on, const T& val ) - { - on.erase( - std::remove(boost::begin(on), boost::end(on), val), - boost::end(on)); - } - - template< class Container, class Pred > - inline void remove_erase_if( Container& on, Pred pred ) - { - on.erase( - std::remove_if(boost::begin(on), boost::end(on), pred), - boost::end(on)); - } +template< class Container > +inline void erase( Container& on, + iterator_range to_erase ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + on.erase( boost::begin(to_erase), boost::end(to_erase) ); } +template< class Container, class T > +inline void remove_erase( Container& on, const T& val ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + on.erase( + std::remove(boost::begin(on), boost::end(on), val), + boost::end(on)); +} + +template< class Container, class Pred > +inline void remove_erase_if( Container& on, Pred pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + on.erase( + std::remove_if(boost::begin(on), boost::end(on), pred), + boost::end(on)); +} + + } // namespace range + using range::erase; + using range::remove_erase; + using range::remove_erase_if; +} // namespace boost + #endif // include guard diff --git a/include/boost/range/algorithm_ext/for_each.hpp b/include/boost/range/algorithm_ext/for_each.hpp index d18f548..6a3b35c 100755 --- a/include/boost/range/algorithm_ext/for_each.hpp +++ b/include/boost/range/algorithm_ext/for_each.hpp @@ -11,6 +11,7 @@ #define BOOST_RANGE_ALGORITHM_EXT_FOR_EACH_HPP_INCLUDED #include +#include #include #include #include @@ -33,33 +34,53 @@ namespace boost } } - template - inline Fn2 for_each(const SinglePassRange1& rng1, const SinglePassRange2& rng2, Fn2 fn) + namespace range { - return range_detail::for_each_impl(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), fn); - } + template + inline Fn2 for_each(const SinglePassRange1& rng1, const SinglePassRange2& rng2, Fn2 fn) + { + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - template - inline Fn2 for_each(const SinglePassRange1& rng1, SinglePassRange2& rng2, Fn2 fn) - { - return range_detail::for_each_impl(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), fn); - } + return ::boost::range_detail::for_each_impl( + ::boost::begin(rng1), ::boost::end(rng1), + ::boost::begin(rng2), ::boost::end(rng2), fn); + } - template - inline Fn2 for_each(SinglePassRange1& rng1, const SinglePassRange2& rng2, Fn2 fn) - { - return range_detail::for_each_impl(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), fn); - } + template + inline Fn2 for_each(const SinglePassRange1& rng1, SinglePassRange2& rng2, Fn2 fn) + { + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - template - inline Fn2 for_each(SinglePassRange1& rng1, SinglePassRange2& rng2, Fn2 fn) - { - return range_detail::for_each_impl(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), fn); - } -} + return ::boost::range_detail::for_each_impl( + ::boost::begin(rng1), ::boost::end(rng1), + ::boost::begin(rng2), ::boost::end(rng2), fn); + } + + template + inline Fn2 for_each(SinglePassRange1& rng1, const SinglePassRange2& rng2, Fn2 fn) + { + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + return ::boost::range_detail::for_each_impl( + ::boost::begin(rng1), ::boost::end(rng1), + ::boost::begin(rng2), ::boost::end(rng2), fn); + } + + template + inline Fn2 for_each(SinglePassRange1& rng1, SinglePassRange2& rng2, Fn2 fn) + { + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + return ::boost::range_detail::for_each_impl( + ::boost::begin(rng1), ::boost::end(rng1), + ::boost::begin(rng2), ::boost::end(rng2), fn); + } + } // namespace range + using range::for_each; +} // namespace boost #endif // include guard diff --git a/include/boost/range/algorithm_ext/insert.hpp b/include/boost/range/algorithm_ext/insert.hpp index 4b18fea..a887f15 100755 --- a/include/boost/range/algorithm_ext/insert.hpp +++ b/include/boost/range/algorithm_ext/insert.hpp @@ -11,6 +11,7 @@ #define BOOST_RANGE_ALGORITHM_EXT_INSERT_HPP_INCLUDED #include +#include #include #include #include @@ -18,15 +19,23 @@ namespace boost { - template< class Container, class Range > - inline void insert( Container& on, - BOOST_DEDUCED_TYPENAME Container::iterator before, - const Range& from ) - { - BOOST_ASSERT( (void*)&on != (void*)&from && - "cannot copy from a container to itself" ); - on.insert( before, boost::begin(from), boost::end(from) ); - } + namespace range + { + +template< class Container, class Range > +inline void insert( Container& on, + BOOST_DEDUCED_TYPENAME Container::iterator before, + const Range& from ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_ASSERT( (void*)&on != (void*)&from && + "cannot copy from a container to itself" ); + on.insert( before, boost::begin(from), boost::end(from) ); } + } // namespace range + using range::insert; +} // namespace boost + #endif // include guard diff --git a/include/boost/range/algorithm_ext/iota.hpp b/include/boost/range/algorithm_ext/iota.hpp new file mode 100644 index 0000000..4a03a59 --- /dev/null +++ b/include/boost/range/algorithm_ext/iota.hpp @@ -0,0 +1,39 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. 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/ +// +#ifndef BOOST_RANGE_ALGORITHM_EXT_IOTA_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_EXT_IOTA_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +template< class ForwardRange, class Value > +inline void iota( ForwardRange& rng, Value x ) +{ + BOOST_CONCEPT_ASSERT(( ForwardRangeConcept )); + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iterator_t; + + iterator_t last_target = ::boost::end(rng); + for (iterator_t target = ::boost::begin(rng); target != last_target; ++target, ++x) + *target = x; +} + + } // namespace range + using range::iota; +} // namespace boost + +#endif // include guard diff --git a/include/boost/range/algorithm_ext/is_sorted.hpp b/include/boost/range/algorithm_ext/is_sorted.hpp index e3e51e2..69ead10 100755 --- a/include/boost/range/algorithm_ext/is_sorted.hpp +++ b/include/boost/range/algorithm_ext/is_sorted.hpp @@ -20,7 +20,7 @@ namespace boost { namespace range_detail { - template + template inline bool is_sorted(ForwardIterator first, ForwardIterator last) { for (ForwardIterator next = first; first != last && ++next != last; ++first) @@ -29,7 +29,7 @@ namespace boost return true; } - template + template inline bool is_sorted(ForwardIterator first, ForwardIterator last, BinaryPredicate pred) { for (ForwardIterator next = first; first != last && ++next != last; ++first) @@ -39,27 +39,33 @@ namespace boost } } - /// \brief template function count - /// - /// range-based version of the count std algorithm - /// - /// \pre SinglePassRange is a model of the SinglePassRangeConcept - template - inline bool is_sorted(const SinglePassRange& rng) + namespace range { - BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); - BOOST_RANGE_CONCEPT_ASSERT((LessThanComparableConcept::type>)); - return range_detail::is_sorted(boost::begin(rng), boost::end(rng)); - } - /// \overload - template - inline bool is_sorted(const SinglePassRange& rng, BinaryPredicate pred) - { - BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); - BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, typename range_value::type>)); - return range_detail::is_sorted(boost::begin(rng), boost::end(rng), pred); - } +/// \brief template function count +/// +/// range-based version of the count std algorithm +/// +/// \pre SinglePassRange is a model of the SinglePassRangeConcept +template +inline bool is_sorted(const SinglePassRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + BOOST_RANGE_CONCEPT_ASSERT((LessThanComparableConcept::type>)); + return range_detail::is_sorted(boost::begin(rng), boost::end(rng)); } +/// \overload +template +inline bool is_sorted(const SinglePassRange& rng, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, BOOST_DEDUCED_TYPENAME range_value::type>)); + return range_detail::is_sorted(boost::begin(rng), boost::end(rng), pred); +} + + } // namespace range + using range::is_sorted; +} // namespace boost + #endif // include guard diff --git a/include/boost/range/algorithm_ext/overwrite.hpp b/include/boost/range/algorithm_ext/overwrite.hpp index 8035968..d2cf4ed 100755 --- a/include/boost/range/algorithm_ext/overwrite.hpp +++ b/include/boost/range/algorithm_ext/overwrite.hpp @@ -11,36 +11,47 @@ #define BOOST_RANGE_ALGORITHM_EXT_OVERWRITE_HPP_INCLUDED #include +#include #include +#include #include #include #include namespace boost { - template< class SinglePassRange1, class SinglePassRange2 > - inline void overwrite( const SinglePassRange1& from, SinglePassRange2& to ) - { - BOOST_DEDUCED_TYPENAME range_iterator::type - i = boost::begin(from), e = boost::end(from); + namespace range + { + +template< class SinglePassRange1, class SinglePassRange2 > +inline void overwrite( const SinglePassRange1& from, SinglePassRange2& to ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + BOOST_DEDUCED_TYPENAME range_iterator::type + i = boost::begin(from), e = boost::end(from); + + BOOST_DEDUCED_TYPENAME range_iterator::type + out = boost::begin(to); - BOOST_DEDUCED_TYPENAME range_iterator::type - out = boost::begin(to); - #ifndef NDEBUG - BOOST_DEDUCED_TYPENAME range_iterator::type - last_out = boost::end(to); + BOOST_DEDUCED_TYPENAME range_iterator::type + last_out = boost::end(to); #endif - for( ; i != e; ++out, ++i ) - { + for( ; i != e; ++out, ++i ) + { #ifndef NDEBUG - BOOST_ASSERT( out != last_out - && "out of bounds in boost::overwrite()" ); + BOOST_ASSERT( out != last_out + && "out of bounds in boost::overwrite()" ); #endif - *out = *i; - } - } + *out = *i; + } } + } // namespace range + using range::overwrite; +} // namespace boost + #endif // include guard diff --git a/include/boost/range/algorithm_ext/push_back.hpp b/include/boost/range/algorithm_ext/push_back.hpp index 8178f5b..e52de41 100755 --- a/include/boost/range/algorithm_ext/push_back.hpp +++ b/include/boost/range/algorithm_ext/push_back.hpp @@ -11,6 +11,7 @@ #define BOOST_RANGE_ALGORITHM_EXT_PUSH_BACK_HPP_INCLUDED #include +#include #include #include #include @@ -18,14 +19,21 @@ namespace boost { - template< class Container, class Range > - inline void push_back( Container& on, const Range& from ) - { - BOOST_ASSERT( (void*)&on != (void*)&from && - "cannot copy from a container to itself" ); - on.insert( on.end(), boost::begin(from), boost::end(from) ); - } + namespace range + { +template< class Container, class Range > +inline void push_back( Container& on, const Range& from ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_ASSERT( (void*)&on != (void*)&from && + "cannot copy from a container to itself" ); + on.insert( on.end(), boost::begin(from), boost::end(from) ); } + } // namespace range + using range::push_back; +} // namespace boost + #endif // include guard diff --git a/include/boost/range/algorithm_ext/push_front.hpp b/include/boost/range/algorithm_ext/push_front.hpp index eb82cf2..6ee269b 100755 --- a/include/boost/range/algorithm_ext/push_front.hpp +++ b/include/boost/range/algorithm_ext/push_front.hpp @@ -11,6 +11,7 @@ #define BOOST_RANGE_ALGORITHM_EXT_PUSH_FRONT_HPP_INCLUDED #include +#include #include #include #include @@ -18,13 +19,21 @@ namespace boost { - template< class Container, class Range > - inline void push_front( Container& on, const Range& from ) - { - BOOST_ASSERT( (void*)&on != (void*)&from && - "cannot copy from a container to itself" ); - on.insert( on.begin(), boost::begin(from), boost::end(from) ); - } + namespace range + { + +template< class Container, class Range > +inline void push_front( Container& on, const Range& from ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_ASSERT( (void*)&on != (void*)&from && + "cannot copy from a container to itself" ); + on.insert( on.begin(), boost::begin(from), boost::end(from) ); } + } // namespace range + using range::push_front; +} // namespace boost + #endif // include guard diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 8cf4d7f..97600d5 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -106,6 +106,15 @@ test-suite range : [ range-test algorithm_test/transform ] [ range-test algorithm_test/unique ] [ range-test algorithm_test/upper_bound ] + [ range-test algorithm_ext_test/copy_n ] + [ range-test algorithm_ext_test/erase ] + [ range-test algorithm_ext_test/for_each_ext ] + [ range-test algorithm_ext_test/insert ] + [ range-test algorithm_ext_test/iota ] + [ range-test algorithm_ext_test/is_sorted ] + [ range-test algorithm_ext_test/overwrite ] + [ range-test algorithm_ext_test/push_back ] + [ range-test algorithm_ext_test/push_front ] [ range-test adl_conformance ] [ range-test adl_conformance_no_using ] [ range-test algorithm ] diff --git a/test/algorithm_ext_test/copy_n.cpp b/test/algorithm_ext_test/copy_n.cpp new file mode 100644 index 0000000..854962f --- /dev/null +++ b/test/algorithm_ext_test/copy_n.cpp @@ -0,0 +1,60 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. 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 +#include +#include +#include + +namespace +{ + template< class Container > + void test_copy_n_impl() + { + std::vector source; + for (std::size_t i = 0; i < 10; ++i) + source.push_back(i); + + for (std::size_t k = 0; k < 10; ++k) + { + std::vector reference; + for (std::size_t j = 0; j < k; ++j) + reference.push_back(j); + + Container test; + boost::copy_n(source, k, std::back_inserter(test)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + } + + void test_copy_n() + { + test_copy_n_impl< std::vector >(); + test_copy_n_impl< std::list >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm_ext.copy_n" ); + + test->add( BOOST_TEST_CASE( &test_copy_n ) ); + + return test; +} diff --git a/test/algorithm_ext_test/erase.cpp b/test/algorithm_ext_test/erase.cpp new file mode 100644 index 0000000..3bdf2da --- /dev/null +++ b/test/algorithm_ext_test/erase.cpp @@ -0,0 +1,128 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. 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 +#include +#include +#include + +namespace +{ + template< class Container > + void test_erase_impl() + { + Container source; + for (int i = 0; i < 10; ++i) + source.push_back(i); + + Container reference(source); + Container test(source); + + typedef BOOST_DEDUCED_TYPENAME Container::iterator iterator_t; + + iterator_t first_ref = reference.begin(); + iterator_t last_ref = reference.end(); + + boost::iterator_range< iterator_t > test_range(test.begin(), test.end()); + + reference.erase(first_ref, last_ref); + boost::erase(test, test_range); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + + void test_erase() + { + test_erase_impl >(); + test_erase_impl >(); + } + + template< class Container > + void test_remove_erase_impl() + { + Container source; + for (int i = 0; i < 10; ++i) + source.push_back(i); + + Container reference(source); + Container test(source); + + boost::remove_erase(test, 5); + + reference.erase( std::find(reference.begin(), reference.end(), 5) ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + + void test_remove_erase() + { + test_remove_erase_impl >(); + test_remove_erase_impl >(); + } + + struct is_even + { + typedef bool result_type; + typedef int argument_type; + bool operator()(int x) const { return x % 2 == 0; } + }; + + template< class Container > + void test_remove_erase_if_impl() + { + Container source; + for (int i = 0; i < 10; ++i) + source.push_back(i); + + Container reference; + typedef BOOST_DEDUCED_TYPENAME Container::const_iterator iterator_t; + iterator_t last_source = source.end(); + is_even pred; + for (iterator_t it_source = source.begin(); it_source != last_source; ++it_source) + { + if (!pred(*it_source)) + reference.push_back(*it_source); + } + + Container test(source); + boost::remove_erase_if(test, is_even()); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + } + + void test_remove_erase_if() + { + test_remove_erase_if_impl >(); + test_remove_erase_if_impl >(); + } + +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm_ext.erase" ); + + test->add( BOOST_TEST_CASE( &test_erase ) ); + test->add( BOOST_TEST_CASE( &test_remove_erase ) ); + test->add( BOOST_TEST_CASE( &test_remove_erase_if ) ); + + return test; +} diff --git a/test/algorithm_ext_test/for_each_ext.cpp b/test/algorithm_ext_test/for_each_ext.cpp new file mode 100644 index 0000000..9df16c5 --- /dev/null +++ b/test/algorithm_ext_test/for_each_ext.cpp @@ -0,0 +1,98 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. 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 +#include +#include +#include + +namespace +{ + struct MockBinaryFn + { + typedef void result_type; + typedef int first_argument_type; + typedef int second_argument_type; + + void operator()(int x, int y) + { + xs.push_back(x); + ys.push_back(y); + } + + std::vector xs; + std::vector ys; + }; + + template< class Range1, class Range2 > + void test_for_each_impl( Range1& rng1, Range2& rng2 ) + { + MockBinaryFn fn = boost::range::for_each(rng1, rng2, MockBinaryFn()); + + BOOST_CHECK_EQUAL_COLLECTIONS( ::boost::begin(rng1), ::boost::end(rng1), + fn.xs.begin(), fn.xs.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( ::boost::begin(rng2), ::boost::end(rng2), + fn.ys.begin(), fn.ys.end() ); + } + + template< class Collection1, class Collection2 > + void test_for_each_impl(const int max_count) + { + Collection1 c1; + for (int i = 0; i < max_count; ++i) + c1.push_back(i); + + Collection2 c2; + for (int i = 0; i < max_count; ++i) + c2.push_back(i); + + test_for_each_impl(c1, c2); + + const Collection1& const_c1 = c1; + const Collection2& const_c2 = c2; + + test_for_each_impl(c1, const_c2); + test_for_each_impl(const_c1, c2); + test_for_each_impl(const_c1, const_c2); + } + + template< class Collection1, class Collection2 > + void test_for_each_impl() + { + test_for_each_impl< Collection1, Collection2 >(0); + test_for_each_impl< Collection1, Collection2 >(1); + test_for_each_impl< Collection1, Collection2 >(10); + } + + void test_for_each() + { + test_for_each_impl< std::vector, std::vector >(); + test_for_each_impl< std::list, std::list >(); + test_for_each_impl< std::vector, std::list >(); + test_for_each_impl< std::list, std::vector >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm_ext.for_each" ); + + test->add( BOOST_TEST_CASE( &test_for_each ) ); + + return test; +} diff --git a/test/algorithm_ext_test/insert.cpp b/test/algorithm_ext_test/insert.cpp new file mode 100644 index 0000000..ff1f706 --- /dev/null +++ b/test/algorithm_ext_test/insert.cpp @@ -0,0 +1,72 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. 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 +#include +#include +#include +#include + +namespace +{ + template< class Container > + void test_insert_impl( int n ) + { + Container test; + boost::insert( test, test.end(), boost::irange(0, n) ); + + Container reference; + for (int i = 0; i < n; ++i) + reference.push_back(i); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + // Do it again so that we are inserting into a non-empty target + boost::insert( test, test.end(), boost::irange(0, n) ); + + for (int j = 0; j < n; ++j) + reference.push_back(j); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + + template< class Container > + void test_insert_impl() + { + test_insert_impl< Container >(0); + test_insert_impl< Container >(1); + test_insert_impl< Container >(2); + test_insert_impl< Container >(100); + } + + void test_insert() + { + test_insert_impl< std::vector >(); + test_insert_impl< std::list >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm_ext.insert" ); + + test->add( BOOST_TEST_CASE( &test_insert ) ); + + return test; +} diff --git a/test/algorithm_ext_test/iota.cpp b/test/algorithm_ext_test/iota.cpp new file mode 100644 index 0000000..64d9b0e --- /dev/null +++ b/test/algorithm_ext_test/iota.cpp @@ -0,0 +1,70 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. 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 +#include +#include +#include + +namespace +{ + template< class Container > + void test_iota_impl(std::size_t n) + { + Container test; + test.resize( n ); + boost::iota( test, n ); + + Container reference; + reference.resize( n ); + std::size_t i = n; + typedef BOOST_DEDUCED_TYPENAME Container::iterator iterator_t; + iterator_t last = reference.end(); + for (iterator_t it = reference.begin(); it != last; ++it, ++i) + { + *it = i; + } + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + } + + template< class Container > + void test_iota_impl() + { + test_iota_impl< Container >(0); + test_iota_impl< Container >(1); + test_iota_impl< Container >(2); + test_iota_impl< Container >(100); + } + + void test_iota() + { + test_iota_impl< std::vector >(); + test_iota_impl< std::list >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm_ext.iota" ); + + test->add( BOOST_TEST_CASE( &test_iota ) ); + + return test; +} diff --git a/test/algorithm_ext_test/is_sorted.cpp b/test/algorithm_ext_test/is_sorted.cpp new file mode 100644 index 0000000..bddc5f8 --- /dev/null +++ b/test/algorithm_ext_test/is_sorted.cpp @@ -0,0 +1,62 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. 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 +#include +#include +#include + +namespace +{ + template< class Container > + void test_is_sorted_impl() + { + Container ascending; + Container descending; + + // Empty ranges are regarded as sorted against any predicate. + BOOST_CHECK( boost::is_sorted(ascending) ); + BOOST_CHECK( boost::is_sorted(ascending, std::less()) ); + BOOST_CHECK( boost::is_sorted(ascending, std::greater()) ); + + for (std::size_t i = 0; i < 10; ++i) + { + ascending.push_back(i); + descending.push_back(9 - i); + } + + BOOST_CHECK( boost::is_sorted(ascending) ); + BOOST_CHECK( !boost::is_sorted(descending) ); + BOOST_CHECK( !boost::is_sorted(ascending, std::greater()) ); + BOOST_CHECK( boost::is_sorted(descending, std::greater()) ); + } + + void test_is_sorted() + { + test_is_sorted_impl< std::vector >(); + test_is_sorted_impl< std::list >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm_ext.is_sorted" ); + + test->add( BOOST_TEST_CASE( &test_is_sorted ) ); + + return test; +} diff --git a/test/algorithm_ext_test/overwrite.cpp b/test/algorithm_ext_test/overwrite.cpp new file mode 100644 index 0000000..0d8604a --- /dev/null +++ b/test/algorithm_ext_test/overwrite.cpp @@ -0,0 +1,74 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. 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 +#include +#include +#include + +namespace +{ + template< class Container > + void test_overwrite_impl(std::size_t n) + { + Container overwrite_source; + for (std::size_t i = 0; i < n; ++i) + overwrite_source.push_back(i); + + Container reference; + reference.resize(n); + std::copy(overwrite_source.begin(), overwrite_source.end(), reference.begin()); + + Container test; + test.resize(n); + boost::overwrite(overwrite_source, test); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + test.clear(); + test.resize(n); + const Container& const_overwrite_source = overwrite_source; + boost::overwrite(const_overwrite_source, test); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + + template< class Container > + void test_overwrite_impl() + { + test_overwrite_impl(0); + test_overwrite_impl(1); + test_overwrite_impl(10); + } + + void test_overwrite() + { + test_overwrite_impl< std::vector >(); + test_overwrite_impl< std::list >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm_ext.overwrite" ); + + test->add( BOOST_TEST_CASE( &test_overwrite ) ); + + return test; +} diff --git a/test/algorithm_ext_test/push_back.cpp b/test/algorithm_ext_test/push_back.cpp new file mode 100644 index 0000000..7e9d539 --- /dev/null +++ b/test/algorithm_ext_test/push_back.cpp @@ -0,0 +1,72 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. 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 +#include +#include +#include +#include + +namespace +{ + template< class Container > + void test_push_back_impl(std::size_t n) + { + Container reference; + for (std::size_t i = 0; i < n; ++i) + reference.push_back(i); + + Container test; + boost::push_back(test, boost::irange(0, n)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + // Do it again to push onto non-empty container + for (std::size_t j = 0; j < n; ++j) + reference.push_back(j); + + boost::push_back(test, boost::irange(0, n)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + + template< class Container > + void test_push_back_impl() + { + test_push_back_impl< Container >(0); + test_push_back_impl< Container >(1); + test_push_back_impl< Container >(2); + test_push_back_impl< Container >(100); + } + + void test_push_back() + { + test_push_back_impl< std::vector >(); + test_push_back_impl< std::list >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm_ext.push_back" ); + + test->add( BOOST_TEST_CASE( &test_push_back ) ); + + return test; +} diff --git a/test/algorithm_ext_test/push_front.cpp b/test/algorithm_ext_test/push_front.cpp new file mode 100644 index 0000000..ebc09a8 --- /dev/null +++ b/test/algorithm_ext_test/push_front.cpp @@ -0,0 +1,71 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. 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 +#include +#include +#include +#include + +namespace +{ + template< class Container > + void test_push_front_impl(std::size_t n) + { + Container reference; + for (std::size_t i = 0; i < n; ++i) + reference.push_back(i); + + Container test; + boost::push_front(test, boost::irange(0, n)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + // Do it again to push onto non-empty container + reference.insert(reference.begin(), reference.begin(), reference.end()); + + boost::push_front(test, boost::irange(0, n)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + + template< class Container > + void test_push_front_impl() + { + test_push_front_impl< Container >(0); + test_push_front_impl< Container >(1); + test_push_front_impl< Container >(2); + test_push_front_impl< Container >(100); + } + + void test_push_front() + { + test_push_front_impl< std::vector >(); + test_push_front_impl< std::list >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm_ext.push_front" ); + + test->add( BOOST_TEST_CASE( &test_push_front ) ); + + return test; +}