Algorithms from BoostCon 'Library in a week'

[SVN r45440]
This commit is contained in:
Marshall Clow
2008-05-16 18:14:08 +00:00
parent 7850e71c9e
commit 003a58264f
6 changed files with 873 additions and 0 deletions

18
copy/test/Jamfile.v2 Normal file
View File

@ -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 ]
;
}

250
copy/test/copy_test.cpp Normal file
View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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