Boost logo

Boost-Commit :

From: marshall_at_[hidden]
Date: 2008-05-16 14:14:09


Author: marshall
Date: 2008-05-16 14:14:08 EDT (Fri, 16 May 2008)
New Revision: 45440
URL: http://svn.boost.org/trac/boost/changeset/45440

Log:
Algorithms from BoostCon 'Library in a week'
Added:
   sandbox/boost/algorithm/all.hpp (contents, props changed)
   sandbox/boost/algorithm/copy.hpp (contents, props changed)
   sandbox/boost/algorithm/for_each_if.hpp (contents, props changed)
   sandbox/boost/algorithm/select.hpp (contents, props changed)
   sandbox/libs/algorithm/copy/
   sandbox/libs/algorithm/copy/test/
   sandbox/libs/algorithm/copy/test/Jamfile.v2 (contents, props changed)
   sandbox/libs/algorithm/copy/test/copy_test.cpp (contents, props changed)

Added: sandbox/boost/algorithm/all.hpp
==============================================================================
--- (empty file)
+++ sandbox/boost/algorithm/all.hpp 2008-05-16 14:14:08 EDT (Fri, 16 May 2008)
@@ -0,0 +1,260 @@
+/*
+ Copyright (c) Marshall Clow 2008.
+
+ 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)
+
+ Revision history:
+ 05 May 2008 mtc First version - as part of BoostCon 2008
+*/
+
+// Returns true iff all of the elements in [ first, last ) satisfy the predicate.
+
+#ifndef BOOST_ALGORITHM_ALL_HPP
+#define BOOST_ALGORITHM_ALL_HPP
+
+#include <boost/range.hpp> // For boost::begin and boost::end
+
+/// \file all.hpp
+/// \brief Boost implementation of various STL-type logical algorithms
+/// \author Marshall Clow
+
+
+namespace boost { namespace algorithm {
+
+/// \fn all ( I first, I last, V val )
+/// \brief Returns true if all elements in [first, last) are equal to 'val'
+///
+/// \param first The start of the input sequence
+/// \param last One past the end of the input sequence
+/// \param val A value to compare against
+///
+ template<typename I, typename V>
+ bool all ( I first, I last, const V &val )
+ {
+ while (first != last) {
+ if ( *first++ != val )
+ return false;
+ }
+ return true;
+ }
+
+/// \fn all ( Range range, V val )
+/// \brief Returns true if all elements in the range are equal to 'val'
+///
+/// \param range The input range
+/// \param val A value to compare against
+///
+ template<typename Range, typename V>
+ bool all ( Range range, const V &val )
+ {
+ return all ( boost::begin ( range ), boost::end ( range ), val );
+ }
+
+
+/// \fn all_if ( I first, I last, Pred p )
+/// \brief Returns true if all elements in [first, last) satisfy the predicate
+///
+/// \param first The start of the input sequence
+/// \param last One past the end of the input sequence
+/// \param p A predicate
+///
+template<typename I, typename Pred>
+ bool all_if ( I first, I last, Pred p )
+ {
+ while (first != last) {
+ if ( !p(*first++))
+ return false;
+ }
+ return true;
+ }
+
+/// \fn all_if ( Range range, Pred p )
+/// \brief Returns true if all elements in the range satisfy the predicate
+///
+/// \param range The input range
+/// \param p A predicate to test the elements
+///
+ template<typename Range, typename Pred>
+ bool all_if ( Range range, Pred p )
+ {
+ return all_if ( boost::begin ( range ), boost::end ( range ), p );
+ }
+
+/// \fn none ( I first, I last, V val )
+/// \brief Returns true if none of the elements in [first, last) are equal to 'val'
+///
+/// \param first The start of the input sequence
+/// \param last One past the end of the input sequence
+/// \param val A value to compare against
+///
+ template<typename I, typename V>
+ bool none ( I first, I last, const V &val )
+ {
+ while (first != last) {
+ if ( *first++ == val )
+ return true;
+ }
+ return false;
+ }
+
+/// \fn none ( Range range, V val )
+/// \brief Returns true if none of the elements in the range are equal to 'val'
+///
+/// \param range The input range
+/// \param val A value to compare against
+///
+ template<typename Range, typename V>
+ bool none ( Range range, const V & val )
+ {
+ return none ( boost::begin ( range ), boost::end ( range ), val );
+ }
+
+
+/// \fn none_if ( I first, I last, Pred p )
+/// \brief Returns true if none of the elements in [first, last) satisfy the predicate
+///
+/// \param first The start of the input sequence
+/// \param last One past the end of the input sequence
+/// \param p A predicate
+///
+template<typename I, typename Pred>
+ bool none_if ( I first, I last, Pred p )
+ {
+ while (first != last) {
+ if ( p(*first++))
+ return false;
+ }
+ return true;
+ }
+
+/// \fn none_if ( Range range, Pred p )
+/// \brief Returns true if none of the elements in the range satisfy the predicate
+///
+/// \param range The input range
+/// \param p A predicate to test the elements
+///
+ template<typename Range, typename Pred>
+ bool none_if ( Range range, Pred p )
+ {
+ return none_if ( boost::begin ( range ), boost::end ( range ), p );
+ }
+
+/// \fn any ( I first, I last, V val )
+/// \brief Returns true if any of the elements in [first, last) are equal to 'val'
+///
+/// \param first The start of the input sequence
+/// \param last One past the end of the input sequence
+/// \param val A value to compare against
+///
+ template<typename I, typename V>
+ bool any ( I first, I last, const V &val )
+ {
+ while (first != last) {
+ if ( *first++ == val )
+ return true;
+ }
+ return false;
+ }
+
+/// \fn any ( Range range, V val )
+/// \brief Returns true if any of the elements in the range are equal to 'val'
+///
+/// \param range The input range
+/// \param val A value to compare against
+///
+ template<typename Range, typename V>
+ bool any ( Range range, const V &val )
+ {
+ return any ( boost::begin ( range ), boost::end ( range ), val );
+ }
+
+/// \fn any_if ( I first, I last, Pred p )
+/// \brief Returns true if any of the elements in [first, last) satisfy the predicate
+///
+/// \param first The start of the input sequence
+/// \param last One past the end of the input sequence
+/// \param p A predicate
+///
+ template<typename I, typename Pred>
+ bool any_if ( I first, I last, Pred p)
+ {
+ while (first != last) {
+ if ( p(*first++))
+ return true;
+ }
+ return false;
+ }
+
+/// \fn any_if ( Range range, Pred p )
+/// \brief Returns true if any elements in the range satisfy the predicate
+///
+/// \param range The input range
+/// \param p A predicate to test the elements
+///
+ template<typename Range, typename Pred>
+ bool any_if ( Range range, Pred p )
+ {
+ return any_if ( boost::begin ( range ), boost::end ( range ), p );
+ }
+
+/// \fn exists_and_only ( I first, I last, V val )
+/// \brief Returns true if the value 'val' exists only once in [first, last).
+///
+/// \param first The start of the input sequence
+/// \param last One past the end of the input sequence
+/// \param val A value to compare against
+///
+ template<typename I, typename V>
+ bool exists_and_only ( I first, I last, const V &val )
+ {
+ I i = std::find (first, last, val);
+ if (i == last) return false;
+ if ( std::find (++i, last, val) != last) return false;
+ return true;
+ }
+
+/// \fn exists_and_only ( Range range, V val )
+/// \brief Returns true if the value 'val' exists only once in the range.
+///
+/// \param range The input range
+/// \param val A value to compare against
+///
+ template<typename Range, typename V>
+ bool exists_and_only ( Range range, const V &val )
+ {
+ return exists_and_only ( boost::begin ( range ), boost::end ( range ), val );
+ }
+
+/// \fn exists_and_only_if ( I first, I last, Pred p )
+/// \brief Returns true if the predicate 'p' is true for exactly one item in [first, last).
+///
+/// \param first The start of the input sequence
+/// \param last One past the end of the input sequence
+/// \param p A predicate to test the elements
+///
+ template<typename I, typename Pred>
+ bool exists_and_only_if ( I first, I last, Pred p )
+ {
+ I i = find_if (first, last, p);
+ if (i == last) return false;
+ if (find_if(++i, last, p) != last) return false;
+ return true;
+ }
+
+/// \fn exists_and_only_if ( Range range, Pred p )
+/// \brief Returns true if the predicate 'p' is true for exactly one item in the range.
+///
+/// \param range The input range
+/// \param p A predicate to test the elements
+///
+ template<typename Range, typename Pred>
+ bool exists_and_only_if ( Range range, Pred p )
+ {
+ return exists_and_only_if ( boost::begin ( range ), boost::end ( range ), p );
+ }
+
+
+}} // namespace boost and algorithm
+
+#endif // BOOST_ALGORITHM_ALL_HPP

Added: sandbox/boost/algorithm/copy.hpp
==============================================================================
--- (empty file)
+++ sandbox/boost/algorithm/copy.hpp 2008-05-16 14:14:08 EDT (Fri, 16 May 2008)
@@ -0,0 +1,244 @@
+/*
+ Copyright (c) Marshall Clow 2008.
+
+ 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)
+
+ Revision history:
+ 05 May 2008 mtc First version - as part of BoostCon 2008
+*/
+
+#ifndef BOOST_ALGORITHM_SEQUENCE_COPY_HPP
+#define BOOST_ALGORITHM_SEQUENCE_COPY_HPP
+
+#include <boost/range.hpp> // For boost::begin and boost::end
+
+/// \file copy.hpp
+/// \brief Boost implementation of various STL-type copying algorithms
+/// that were left out of the standard.
+/// \author Marshall Clow
+
+namespace boost { namespace algorithm { namespace sequence {
+
+/// \fn copy_if ( I first, I last, O res, Pred p )
+/// \brief Copies all the elements from [first, last) that satisfy the predicate into 'res'
+///
+/// \param first The start of the input sequence
+/// \param last One past the end of the input sequence
+/// \param res An output iterator to copy into
+/// \param p A predicate to determine which items to copy
+/// \return The (modified) output iterator
+///
+/// \note Based on a suggested implementation by Bjorne Stoustrop.
+///
+ template<typename I, typename O, typename Pred>
+ O copy_if ( I first, I last, O res, Pred p)
+ {
+ while (first != last)
+ {
+ if (p(*first))
+ *res++ = *first;
+ ++first;
+ }
+ return res;
+ }
+
+/// \fn copy_if ( Range range, O res, Pred p )
+/// \brief Copy all the elements from the range that satisfy the predicate into 'res'
+///
+/// \param range The input range
+/// \param res An output iterator to copy into
+/// \param p A predicate to determine which items to copy
+/// \return The (modified) output iterator
+///
+ template<typename Range, typename O, typename Pred>
+ O copy_if ( Range range, O res, Pred p )
+ {
+ return copy_if ( boost::begin ( range ), boost::end ( range ), res, p );
+ }
+
+
+/// \fn copy_backward_if ( I first, I last, O res, Pred p )
+/// \brief Copies all the elements from (last, first] that satisfy the predicate into 'res'
+///
+/// \param first The start of the input sequence
+/// \param last One past the end of the input sequence
+/// \param res An output iterator to copy into
+/// \param p A predicate to determine which items to copy
+/// \return The (modified) output iterator
+///
+/// \note Based on a suggested implementation by Bjorne Stoustrop.
+///
+ template<typename I, typename O, typename Pred>
+ O copy_backward_if ( I first, I last, O res, Pred p)
+ {
+ while (first != last)
+ {
+ if (p(*--last))
+ *res++ = *last;
+ }
+ return res;
+ }
+
+/// \fn copy_backward_if ( Range range, O res, Pred p )
+/// \brief Copy all the elements from the range that satisfy the predicate into 'res'
+///
+/// \param range The input range
+/// \param res An output iterator to copy into
+/// \param p A predicate to determine which items to copy
+/// \return The (modified) output iterator
+///
+ template<typename Range, typename O, typename Pred>
+ O copy_backward_if ( Range range, O res, Pred p )
+ {
+ return copy_backward_if ( boost::begin ( range ), boost::end ( range ), res, p );
+ }
+
+
+/* -- I'd like a value-based version, too; but I don't know of a good name....
+template<typename I,typename O>
+ O copy_equal ( I first, I last, O res, I::value_type val )
+ {
+ while (first != last) {
+ if (*first == val)
+ *res++ = *first;
+ ++first;
+ }
+ return res;
+ }
+*/
+
+
+/// \fn copy_while ( I first, I last, O res, Pred p )
+/// \brief Copies all the elements from [first, last) up to a point into 'res'.\n
+/// Will continue until the input range is exhausted, or the predicate 'p' fails.
+///
+/// \param first The start of the input sequence
+/// \param last One past the end of the input sequence
+/// \param res An output iterator to copy into
+/// \param p A predicate to determine when to stop copying
+/// \return The (modified) output iterator
+///
+ template<typename I, typename O, typename Pred>
+ O copy_while ( I first, I last, O res, Pred p )
+ {
+ for (; first != last && p(*first); ++first)
+ *res++ = *first;
+ return res;
+ }
+
+/// \fn copy_while ( Range range, O res, Pred p )
+/// \brief Copies all the elements from the range up to a point into 'res'.\n
+/// Will continue until the input range is exhausted, or the predicate 'p' fails.
+///
+/// \param range The input range
+/// \param res An output iterator to copy into
+/// \param p A predicate to determine when to stop copying
+/// \return The (modified) output iterator
+///
+ template<typename Range, typename O, typename Pred>
+ O copy_while ( Range range, O res, Pred p )
+ {
+ return copy_while ( boost::begin ( range ), boost::end ( range ), res, p );
+ }
+
+
+/// \fn copy_backward_while ( I first, I last, O res, Pred p )
+/// \brief Copies all the elements from (last, first] up to a point into 'res'.\n
+/// Will continue until the input range is exhausted, or the predicate 'p' fails.
+///
+/// \param first The start of the input sequence
+/// \param last One past the end of the input sequence
+/// \param res An output iterator to copy into
+/// \param p A predicate to determine when to stop copying
+/// \return The (modified) output iterator
+///
+ template<typename I, typename O, typename Pred>
+ O copy_backward_while ( I first, I last, O res, Pred p )
+ {
+ while ( first != last && p ( *--last ))
+ *res++ = *last;
+ return res;
+ }
+
+/// \fn copy_backward_while ( Range range, O res, Pred p )
+/// \brief Copies all the elements from the range up to a point into 'res'.\n
+/// Will continue until the input range is exhausted, or the predicate 'p' fails.
+///
+/// \param range The input range
+/// \param res An output iterator to copy into
+/// \param p A predicate to determine when to stop copying
+/// \return The (modified) output iterator
+///
+ template<typename Range, typename O, typename Pred>
+ O copy_while_backward ( Range range, O res, Pred p )
+ {
+ return copy_backward_while ( boost::begin ( range ), boost::end ( range ), res, p );
+ }
+
+
+// According to Werner Salomon, the challenge for copy_n is that the algorithm should work correctly
+// with an std::istream_iterator. Therefor the input iterator have to increment only N-1 times.
+// Marshall sez: Is that really true?
+// Long discussion starting
+// here <http://www.tech-archive.net/Archive/VC/microsoft.public.vc.stl/2004-05/0112.html>
+// Marshall sez: I'm going to increment N times.
+//
+// Marshall sez: What's the advantage of templatizing on count, rather than using std::size_t?
+//
+// No range-based version here
+
+/// \fn copy_n ( I first, Size count, O res )
+/// \brief Copies n elements starting at 'first' into 'res'.
+///
+/// \param first The start of the input sequence
+/// \param count The number of elements to copy
+/// \param res An output iterator to copy into
+/// \return The (modified) output iterator
+///
+// template <typename I, typename Size, typename O>
+// O copy_n ( I first, Size count, O res )
+ template <typename I, typename O>
+ O copy_n ( I first, typename iterator_traits<I>::difference_type count, O res )
+ {
+ while ( count-- > 0 )
+ *res++ = *first++;
+ return res;
+ }
+
+// Range-based versions of copy and copy_backwards.
+
+/// \fn copy ( Range range, O res )
+/// \brief Copies elements from the range 'range' into 'res'.
+///
+/// \param range The input range
+/// \param res An output iterator to copy into
+/// \return The (modified) output iterator
+///
+/// \note A range-based version of std::copy
+///
+ template<typename Range, typename O>
+ O copy ( Range range, O res )
+ {
+ return std::copy ( boost::begin ( range ), boost::end ( range ), res );
+ }
+
+
+/// \fn copy_backward ( Range range, O res )
+/// \brief Copies elements from the range 'range' into 'res'.
+///
+/// \param range The input range
+/// \param res An output iterator to copy into
+/// \return The (modified) output iterator
+///
+/// \note A range-based version of std::copy_backwards
+///
+ template<typename Range, typename O>
+ O copy_backward ( Range range, O res )
+ {
+ return std::copy_backward ( boost::begin ( range ), boost::end ( range ), res );
+ }
+
+}}} // namespace boost & algorithm & sequence
+
+#endif // BOOST_ALGORITHM_SEQUENCE_COPY_HPP

Added: sandbox/boost/algorithm/for_each_if.hpp
==============================================================================
--- (empty file)
+++ sandbox/boost/algorithm/for_each_if.hpp 2008-05-16 14:14:08 EDT (Fri, 16 May 2008)
@@ -0,0 +1,47 @@
+/*
+ Copyright (c) Marshall Clow 2008.
+
+ 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)
+
+ Revision history:
+ 06 May 2008 mtc First version - as part of BoostCon 2008
+*/
+
+#ifndef BOOST_ALGORITHM_FOR_EACH_IF_HPP
+#define BOOST_ALGORITHM_FOR_EACH_IF_HPP
+
+#include <boost/range.hpp> // For boost::begin and boost::end
+
+/// \file for_each_if.hpp
+/// \brief Boost implementation for_each_if, which was left out of the standard.
+/// \author Marshall Clow
+
+namespace boost { namespace algorithm {
+
+/// \fn for_each_if ( InputIterator first, InputIterator last, Pred p, Func f )
+/// \brief Applies the function_object 'f' to each element in [first, last) that satisfies
+/// the predicate 'p'.
+///
+/// \param first The start of the input sequence
+/// \param last One past the end of the input sequence
+/// \param p A predicate to determine which items to copy
+/// \param f A function object that takes a single argument
+/// \return the function object 'f'
+///
+///
+ template<typename InputIterator, typename Pred, typename Func>
+ UnaryFunction for_each_if ( InputIterator first, InputIterator last, Pred p, Func f )
+ {
+ while ( first != last )
+ {
+ if (p(*first))
+ f(*first);
+ ++first;
+ }
+ return f;
+ }
+
+}} // namespace boost & algorithm
+
+#endif // BOOST_ALGORITHM_FOR_EACH_IF_HPP

Added: sandbox/boost/algorithm/select.hpp
==============================================================================
--- (empty file)
+++ sandbox/boost/algorithm/select.hpp 2008-05-16 14:14:08 EDT (Fri, 16 May 2008)
@@ -0,0 +1,54 @@
+/*
+ Copyright (c) Marshall Clow 2008.
+
+ 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)
+
+ Implemented by SGI in their STL implementation
+ This implemnetation is based on interprocess::detail::select1st by Ion Gaztanaga.
+
+ Revision history:
+ 06 May 2008 mtc First version - as part of BoostCon 2008
+*/
+
+#ifndef BOOST_ALGORITHM_SELECT_HPP
+#define BOOST_ALGORITHM_SELECT_HPP
+
+
+/// \file select.hpp
+/// \brief Boost implementation select1st and select2nd.
+/// \author Marshall Clow
+
+namespace boost { namespace algorithm {
+
+/// \fn select1st
+/// \brief Unary function that returns the first element of a std::pair
+///
+/// \param p The pair.
+/// \return p.first
+///
+///
+ template <class Pair>
+ struct select1st : public std::unary_function<Pair, typename Pair::first_type>
+ {
+ const typename Pair::first_type& operator()(const Pair& p) const { return p.first; }
+ typename Pair::first_type& operator()( Pair& p) const { return p.first; }
+ };
+
+/// \fn select2nd
+/// \brief Unary function that returns the first element of a std::pair
+///
+/// \param p The pair.
+/// \return p.first
+///
+///
+ template <class Pair>
+ struct select2nd : public std::unary_function<Pair, typename Pair::second_type>
+ {
+ const typename Pair::second_type& operator()(const Pair& p) const { return p.second; }
+ typename Pair::second_type& operator()( Pair& p) const { return p.second; }
+ };
+
+}} // namespace boost & algorithm
+
+#endif // BOOST_ALGORITHM_SELECT_HPP

Added: sandbox/libs/algorithm/copy/test/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/libs/algorithm/copy/test/Jamfile.v2 2008-05-16 14:14:08 EDT (Fri, 16 May 2008)
@@ -0,0 +1,18 @@
+# Boost.CopyIf Library test Jamfile
+#
+# Copyright (C) 2008 Marshall Clow
+#
+# 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)
+#
+
+import testing ;
+
+{
+ test-suite algorithm/copy:
+ : [ run copy_test.cpp
+ : : : : copy ]
+ ;
+}
+

Added: sandbox/libs/algorithm/copy/test/copy_test.cpp
==============================================================================
--- (empty file)
+++ sandbox/libs/algorithm/copy/test/copy_test.cpp 2008-05-16 14:14:08 EDT (Fri, 16 May 2008)
@@ -0,0 +1,250 @@
+// (C) Copyright Marshall Clow 2008
+// Use, modification and distribution are 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)
+
+#include <utility>
+#include <functional>
+
+#include <boost/config.hpp>
+#include <boost/algorithm/copy.hpp>
+#include <boost/test/included/test_exec_monitor.hpp>
+
+// #include <boost/algorithm/all.hpp>
+// #include <boost/algorithm/select.hpp>
+
+template <int v> bool IsEqual ( int v2 ) { return v2 == v; }
+template <int v> bool IsNotEqual ( int v2 ) { return v2 != v; }
+template <int v> bool IsGreater ( int v2 ) { return v2 > v; }
+template <int v> bool IsLess ( int v2 ) { return v2 < v; }
+bool IsEven ( int v2 ) { return ( v2 & 1 ) == 0; }
+bool IsOdd ( int v2 ) { return ( v2 & 1 ) != 0; }
+
+void test_copy_if ()
+{
+ const int vals [] = { 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1 };
+ const unsigned int valsSize = sizeof ( vals ) / sizeof ( vals [0] );
+
+ std::vector<int> cont;
+ std::vector<int> res;
+
+// Copy all but the last element
+ std::copy ( vals, vals + valsSize - 1, std::back_inserter(cont));
+
+// Copy_if from constant iterators
+ res.clear ();
+ boost::algorithm::copy_if ( vals, vals + valsSize, std::back_inserter(res), IsEqual<0> );
+ BOOST_CHECK_EQUAL ( res.size (), 5U );
+ BOOST_CHECK ( std::find_if ( res.begin (), res.end (), IsNotEqual<0> ) == res.end ());
+
+// Copy them all
+ res.clear ();
+ boost::algorithm::copy_if ( vals, vals + valsSize, std::back_inserter(res), IsLess<100> );
+ BOOST_CHECK_EQUAL ( valsSize, res.size ());
+ BOOST_CHECK ( std::equal ( vals, vals + valsSize, res.begin ()));
+
+// Copy none
+ res.clear ();
+ boost::algorithm::copy_if ( vals, vals + valsSize, std::back_inserter(res), IsGreater<100> );
+ BOOST_CHECK_EQUAL ( 0U, res.size ());
+
+// Copy_if using ranges
+ res.clear ();
+ boost::algorithm::copy_if ( cont, std::back_inserter(res), IsNotEqual<0> );
+ BOOST_CHECK_EQUAL ( res.size (), 5U );
+ BOOST_CHECK ( std::find_if ( res.begin (), res.end (), IsEqual<0> ) == res.end ());
+
+// Copy them all
+ res.clear ();
+ boost::algorithm::copy_if ( cont, std::back_inserter(res), IsNotEqual<2> );
+ BOOST_CHECK_EQUAL ( cont.size (), res.size ());
+ BOOST_CHECK ( std::equal ( cont.begin (), cont.end (), res.begin ()));
+
+// Copy none
+ res.clear ();
+ boost::algorithm::copy_if ( cont, std::back_inserter(res), IsEqual<2> );
+ BOOST_CHECK_EQUAL ( 0U, res.size ());
+
+// ---- Backwards tests ----
+ const int vals2 [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ const unsigned int vals2Size = sizeof ( vals2 ) / sizeof ( vals2 [0] );
+
+// Copy all but the last element
+ cont.clear ();
+ std::copy ( vals2, vals2 + vals2Size - 1, std::back_inserter(cont));
+
+// Copy_if_backward from constant iterators
+ res.clear ();
+ boost::algorithm::copy_if_backward ( vals2, vals2 + vals2Size, std::back_inserter(res), IsEven );
+ BOOST_CHECK_EQUAL ( res.size (), 5U );
+ BOOST_CHECK_EQUAL ( res[0], 8 );
+ BOOST_CHECK_EQUAL ( res[1], 6 );
+ BOOST_CHECK_EQUAL ( res[2], 4 );
+ BOOST_CHECK_EQUAL ( res[3], 2 );
+ BOOST_CHECK_EQUAL ( res[4], 0 );
+
+// Copy them all
+ res.clear ();
+ boost::algorithm::copy_if_backward ( vals2, vals2 + vals2Size, std::back_inserter(res), IsLess<100> );
+ BOOST_CHECK_EQUAL ( vals2Size, res.size ());
+ BOOST_CHECK ( std::equal ( vals2, vals2 + vals2Size, res.rbegin ()));
+
+// Copy none
+ res.clear ();
+ boost::algorithm::copy_if_backward ( vals, vals + valsSize, std::back_inserter(res), IsGreater<100> );
+ BOOST_CHECK_EQUAL ( 0U, res.size ());
+
+
+// Copy_if_backward using ranges
+ res.clear ();
+ boost::algorithm::copy_if_backward ( cont, std::back_inserter(res), IsEven );
+ BOOST_CHECK_EQUAL ( res.size (), 5U );
+ BOOST_CHECK_EQUAL ( res[0], 8 );
+ BOOST_CHECK_EQUAL ( res[1], 6 );
+ BOOST_CHECK_EQUAL ( res[2], 4 );
+ BOOST_CHECK_EQUAL ( res[3], 2 );
+ BOOST_CHECK_EQUAL ( res[4], 0 );
+
+// Copy them all
+ res.clear ();
+ boost::algorithm::copy_if_backward ( cont, std::back_inserter(res), IsLess<100> );
+ BOOST_CHECK_EQUAL ( cont.size (), res.size ());
+ BOOST_CHECK ( std::equal ( cont.rbegin (), cont.rend (), res.begin ()));
+
+// Copy none
+ res.clear ();
+ boost::algorithm::copy_if_backward ( vals, vals + valsSize, std::back_inserter(res), IsGreater<100> );
+ BOOST_CHECK_EQUAL ( 0U, res.size ());
+}
+
+void test_copy_while ()
+{
+ const int vals [] = { 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1 };
+ const unsigned int valsSize = sizeof ( vals ) / sizeof ( vals [0] );
+
+ std::vector<int> cont;
+ std::vector<int> res;
+
+// Copy all but the last element
+ std::copy ( vals, vals + valsSize - 1, std::back_inserter(cont));
+
+// Copy_while from constant iterators
+ res.clear ();
+ boost::algorithm::copy_while ( vals, vals + valsSize, std::back_inserter(res), IsEqual<0> );
+ BOOST_CHECK_EQUAL ( res.size (), 1U );
+ BOOST_CHECK_EQUAL ( res[0], 0 );
+
+// Copy them all
+ res.clear ();
+ boost::algorithm::copy_while ( vals, vals + valsSize, std::back_inserter(res), IsLess<100> );
+ BOOST_CHECK_EQUAL ( valsSize, res.size ());
+ BOOST_CHECK ( std::equal ( vals, vals + valsSize, res.begin ()));
+
+// Copy none
+ res.clear ();
+ boost::algorithm::copy_while ( vals, vals + valsSize, std::back_inserter(res), IsGreater<100> );
+ BOOST_CHECK_EQUAL ( 0U, res.size ());
+
+// Copy_while using ranges
+ res.clear ();
+ boost::algorithm::copy_while ( cont, std::back_inserter(res), IsNotEqual<1> );
+ BOOST_CHECK_EQUAL ( res.size (), 1U );
+ BOOST_CHECK_EQUAL ( res[0], 0 );
+
+// Copy them all
+ res.clear ();
+ boost::algorithm::copy_while ( cont, std::back_inserter(res), IsNotEqual<2> );
+ BOOST_CHECK_EQUAL ( cont.size (), res.size ());
+ BOOST_CHECK ( std::equal ( cont.begin (), cont.end (), res.begin ()));
+
+// Copy none
+ res.clear ();
+ boost::algorithm::copy_while ( cont, std::back_inserter(res), IsEqual<2> );
+ BOOST_CHECK_EQUAL ( 0U, res.size ());
+
+// ---- Backwards tests ----
+ const int vals2 [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ const unsigned int vals2Size = sizeof ( vals2 ) / sizeof ( vals2 [0] );
+
+// Copy all but the last element
+ cont.clear ();
+ std::copy ( vals2, vals2 + vals2Size - 1, std::back_inserter(cont));
+
+// Copy_if_backward from constant iterators
+ res.clear ();
+ boost::algorithm::copy_while_backward ( vals2, vals2 + vals2Size, std::back_inserter(res), IsGreater<5> );
+ BOOST_CHECK_EQUAL ( res.size (), 4U );
+ BOOST_CHECK_EQUAL ( res[0], 9 );
+ BOOST_CHECK_EQUAL ( res[1], 8 );
+ BOOST_CHECK_EQUAL ( res[2], 7 );
+ BOOST_CHECK_EQUAL ( res[3], 6 );
+
+// Copy them all
+ res.clear ();
+ boost::algorithm::copy_while_backward ( vals2, vals2 + vals2Size, std::back_inserter(res), IsLess<100> );
+ BOOST_CHECK_EQUAL ( vals2Size, res.size ());
+ BOOST_CHECK ( std::equal ( vals2, vals2 + vals2Size, res.rbegin ()));
+
+// Copy none
+ res.clear ();
+ boost::algorithm::copy_while_backward ( vals, vals + valsSize, std::back_inserter(res), IsGreater<100> );
+ BOOST_CHECK_EQUAL ( 0U, res.size ());
+
+
+// Copy_while_backward using ranges
+ res.clear ();
+ boost::algorithm::copy_while_backward ( cont, std::back_inserter(res), IsGreater<5> );
+ BOOST_CHECK_EQUAL ( res.size (), 3U );
+ BOOST_CHECK_EQUAL ( res[0], 8 );
+ BOOST_CHECK_EQUAL ( res[1], 7 );
+ BOOST_CHECK_EQUAL ( res[2], 6 );
+
+// Copy them all
+ res.clear ();
+ boost::algorithm::copy_while_backward ( cont, std::back_inserter(res), IsLess<100> );
+ BOOST_CHECK_EQUAL ( cont.size (), res.size ());
+ BOOST_CHECK ( std::equal ( cont.rbegin (), cont.rend (), res.begin ()));
+
+// Copy none
+ res.clear ();
+ boost::algorithm::copy_while_backward ( vals, vals + valsSize, std::back_inserter(res), IsGreater<100> );
+ BOOST_CHECK_EQUAL ( 0U, res.size ());
+}
+
+void test_copy_n ()
+{
+ const int vals [] = { 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1 };
+ const unsigned int valsSize = sizeof ( vals ) / sizeof ( vals [0] );
+
+ std::vector<int> cont;
+ std::vector<int> res;
+
+// Copy all but the last element
+ std::copy ( vals, vals + valsSize - 1, std::back_inserter(cont));
+
+// copy_n from constant iterators
+ res.clear ();
+ boost::algorithm::copy_n ( vals, valsSize, std::back_inserter(res));
+ BOOST_CHECK_EQUAL ( res.size (), valsSize );
+ BOOST_CHECK ( std::equal ( vals, vals + valsSize, res.begin ()));
+
+// Copy none
+ res.clear ();
+ boost::algorithm::copy_n ( vals, 0, std::back_inserter(res));
+ BOOST_CHECK_EQUAL ( 0U, res.size ());
+
+// Copy_while from container
+ res.clear ();
+ boost::algorithm::copy_n ( cont.begin (), cont.size (), std::back_inserter(res) );
+ BOOST_CHECK_EQUAL ( res.size (), cont.size ());
+ BOOST_CHECK ( std::equal ( cont.begin (), cont.end (), res.begin ()));
+}
+
+
+int test_main( int , char* [] )
+{
+ test_copy_if ();
+ test_copy_while ();
+ test_copy_n ();
+ return 0;
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk