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

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