diff --git a/copy/test/Jamfile.v2 b/copy/test/Jamfile.v2 new file mode 100644 index 0000000..41fc08a --- /dev/null +++ b/copy/test/Jamfile.v2 @@ -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 ] + ; +} + diff --git a/copy/test/copy_test.cpp b/copy/test/copy_test.cpp new file mode 100644 index 0000000..48e0c84 --- /dev/null +++ b/copy/test/copy_test.cpp @@ -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 +#include + +#include +#include +#include + +// #include +// #include + +template bool IsEqual ( int v2 ) { return v2 == v; } +template bool IsNotEqual ( int v2 ) { return v2 != v; } +template bool IsGreater ( int v2 ) { return v2 > v; } +template 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 cont; + std::vector 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 cont; + std::vector 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 cont; + std::vector 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; +} diff --git a/include/boost/algorithm/all.hpp b/include/boost/algorithm/all.hpp new file mode 100644 index 0000000..a6a86ef --- /dev/null +++ b/include/boost/algorithm/all.hpp @@ -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 // 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 diff --git a/include/boost/algorithm/copy.hpp b/include/boost/algorithm/copy.hpp new file mode 100644 index 0000000..cbdf1ca --- /dev/null +++ b/include/boost/algorithm/copy.hpp @@ -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 // 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 +// 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 +// O copy_n ( I first, Size count, O res ) + template + O copy_n ( I first, typename iterator_traits::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 + 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 + 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 diff --git a/include/boost/algorithm/for_each_if.hpp b/include/boost/algorithm/for_each_if.hpp new file mode 100644 index 0000000..0ea9636 --- /dev/null +++ b/include/boost/algorithm/for_each_if.hpp @@ -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 // 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 + 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 diff --git a/include/boost/algorithm/select.hpp b/include/boost/algorithm/select.hpp new file mode 100644 index 0000000..041b988 --- /dev/null +++ b/include/boost/algorithm/select.hpp @@ -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 + struct select1st : public std::unary_function + { + 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 + struct select2nd : public std::unary_function + { + 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