Compare commits

..

1 Commits

Author SHA1 Message Date
Vladimir Prus
da5bce5355 Create branch to keep WIP patch for modular build.
[SVN r85883]
2013-09-25 08:12:19 +00:00
45 changed files with 506 additions and 416 deletions

View File

@@ -22,7 +22,7 @@ Consider the two sequences:
std::equal ( seq1.begin (), seq1.end (), seq2.begin ()); // true std::equal ( seq1.begin (), seq1.end (), seq2.begin ()); // true
std::equal ( seq2.begin (), seq2.end (), seq1.begin ()); // Undefined behavior std::equal ( seq2.begin (), seq2.end (), seq1.begin ()); // Undefined behavior
std::equal ( seq1.begin (), seq1.end (), seq2.begin (), seq2.end ()); // false std::equal ( seq1.begin (), seq1.end (), seq1.begin (), seq2.end ()); // false
``` ```
You can argue that `true` is the correct answer in the first case, even though the sequences are not the same. The first N entries in `seq2` are the same as the entries in `seq1` - but that's not all that's in `seq2`. But in the second case, the algorithm will read past the end of `seq1`, resulting in undefined behavior (large earthquake, incorrect results, pregnant cat, etc). You can argue that `true` is the correct answer in the first case, even though the sequences are not the same. The first N entries in `seq2` are the same as the entries in `seq1` - but that's not all that's in `seq2`. But in the second case, the algorithm will read past the end of `seq1`, resulting in undefined behavior (large earthquake, incorrect results, pregnant cat, etc).

View File

@@ -22,7 +22,7 @@ Consider the two sequences:
std::mismatch ( seq1.begin (), seq1.end (), seq2.begin ()); // <3, 3> std::mismatch ( seq1.begin (), seq1.end (), seq2.begin ()); // <3, 3>
std::mismatch ( seq2.begin (), seq2.end (), seq1.begin ()); // Undefined behavior std::mismatch ( seq2.begin (), seq2.end (), seq1.begin ()); // Undefined behavior
std::mismatch ( seq1.begin (), seq1.end (), seq2.begin (), seq2.end ()); // <3, 3> std::mismatch ( seq1.begin (), seq1.end (), seq1.begin (), seq2.end ()); // <3, 3>
``` ```
The first N entries in `seq2` are the same as the entries in `seq1` - but that's not all that's in `seq2`. In the second case, the algorithm will read past the end of `seq1`, resulting in undefined behavior (large earthquake, incorrect results, pregnant cat, etc). The first N entries in `seq2` are the same as the entries in `seq1` - but that's not all that's in `seq2`. In the second case, the algorithm will read past the end of `seq1`, resulting in undefined behavior (large earthquake, incorrect results, pregnant cat, etc).
@@ -60,7 +60,7 @@ mismatch ( c1.end(), c1.end(), c2.end(), c2.end()) --> <c1.end(),
[heading Complexity] [heading Complexity]
Both of the variants of `mismatch` run in ['O(N)] (linear) time; that is, they compare against each element in the list once. If the sequence is found to be not equal at any point, the routine will terminate immediately, without examining the rest of the elements. Both of the variants of `mismatch` run in ['O(N)] (linear) time; that is, they compare against each element in the list once. If the sequence is found to be equal at any point, the routine will terminate immediately, without examining the rest of the elements.
[heading Exception Safety] [heading Exception Safety]

View File

@@ -19,11 +19,11 @@ The function `is_sorted(sequence)` determines whether or not a sequence is compl
`` ``
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
template <typename ForwardIterator, typename Pred> template <typename Iterator, typename Pred>
bool is_sorted ( ForwardIterator first, ForwardIterator last, Pred p ); bool is_sorted ( Iterator first, Iterator last, Pred p );
template <typename ForwardIterator> template <typename Iterator>
bool is_sorted ( ForwardIterator first, ForwardIterator last ); bool is_sorted ( Iterator first, Iterator last );
template <typename Range, typename Pred> template <typename Range, typename Pred>
@@ -34,7 +34,7 @@ namespace boost { namespace algorithm {
}} }}
`` ``
Iterator requirements: The `is_sorted` functions will work forward iterators or better. Iterator requirements: The `is_sorted` functions will work on all kinds of iterators (except output iterators).
[heading is_sorted_until] [heading is_sorted_until]
@@ -88,8 +88,8 @@ To test if a sequence is decreasing (each element no larger than the preceding o
`` ``
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
template <typename ForwardIterator> template <typename Iterator>
bool is_decreasing ( ForwardIterator first, ForwardIterator last ); bool is_decreasing ( Iterator first, Iterator last );
template <typename R> template <typename R>
bool is_decreasing ( const R &range ); bool is_decreasing ( const R &range );
@@ -99,8 +99,8 @@ namespace boost { namespace algorithm {
To test if a sequence is strictly increasing (each element larger than the preceding one): To test if a sequence is strictly increasing (each element larger than the preceding one):
`` ``
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
template <typename ForwardIterator> template <typename Iterator>
bool is_strictly_increasing ( ForwardIterator first, ForwardIterator last ); bool is_strictly_increasing ( Iterator first, Iterator last );
template <typename R> template <typename R>
bool is_strictly_increasing ( const R &range ); bool is_strictly_increasing ( const R &range );
@@ -110,8 +110,8 @@ namespace boost { namespace algorithm {
To test if a sequence is strictly decreasing (each element smaller than the preceding one): To test if a sequence is strictly decreasing (each element smaller than the preceding one):
`` ``
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
template <typename ForwardIterator> template <typename Iterator>
bool is_strictly_decreasing ( ForwardIterator first, ForwardIterator last ); bool is_strictly_decreasing ( Iterator first, Iterator last );
template <typename R> template <typename R>
bool is_strictly_decreasing ( const R &range ); bool is_strictly_decreasing ( const R &range );

View File

@@ -1,86 +0,0 @@
/*
Copyright (c) Marshall Clow 2014.
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:
2 Dec 2014 mtc First version; power
*/
/// \file algorithm.hpp
/// \brief Misc Algorithms
/// \author Marshall Clow
///
#ifndef BOOST_ALGORITHM_HPP
#define BOOST_ALGORITHM_HPP
#include <boost/utility/enable_if.hpp> // for boost::disable_if
#include <boost/type_traits/is_integral.hpp>
namespace boost { namespace algorithm {
template <typename T>
T identity_operation ( std::multiplies<T> ) { return T(1); }
template <typename T>
T identity_operation ( std::plus<T> ) { return T(0); }
/// \fn power ( T x, Integer n )
/// \return the value "x" raised to the power "n"
///
/// \param x The value to be exponentiated
/// \param n The exponent (must be >= 0)
///
// \remark Taken from Knuth, The Art of Computer Programming, Volume 2:
// Seminumerical Algorithms, Section 4.6.3
template <typename T, typename Integer>
typename boost::enable_if<boost::is_integral<Integer>, T>::type
power (T x, Integer n) {
T y = 1; // Should be "T y{1};"
if (n == 0) return y;
while (true) {
if (n % 2 == 1) {
y = x * y;
if (n == 1)
return y;
}
n = n / 2;
x = x * x;
}
return y;
}
/// \fn power ( T x, Integer n, Operation op )
/// \return the value "x" raised to the power "n"
/// using the operaton "op".
///
/// \param x The value to be exponentiated
/// \param n The exponent (must be >= 0)
/// \param op The operation used
///
// \remark Taken from Knuth, The Art of Computer Programming, Volume 2:
// Seminumerical Algorithms, Section 4.6.3
template <typename T, typename Integer, typename Operation>
typename boost::enable_if<boost::is_integral<Integer>, T>::type
power (T x, Integer n, Operation op) {
T y = identity_operation(op);
if (n == 0) return y;
while (true) {
if (n % 2 == 1) {
y = op(x, y);
if (n == 1)
return y;
}
n = n / 2;
x = op(x, x);
}
return y;
}
}}
#endif // BOOST_ALGORITHM_HPP

View File

@@ -31,8 +31,8 @@
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
/// \fn clamp ( T const& val, /// \fn clamp ( T const& val,
/// typename boost::mpl::identity<T>::type const & lo, /// typename boost::mpl::identity<T>::type const& lo,
/// typename boost::mpl::identity<T>::type const & hi, Pred p ) /// typename boost::mpl::identity<T>::type const& hi, Pred p )
/// \return the value "val" brought into the range [ lo, hi ] /// \return the value "val" brought into the range [ lo, hi ]
/// using the comparison predicate p. /// using the comparison predicate p.
/// If p ( val, lo ) return lo. /// If p ( val, lo ) return lo.
@@ -56,8 +56,8 @@ namespace boost { namespace algorithm {
/// \fn clamp ( T const& val, /// \fn clamp ( T const& val,
/// typename boost::mpl::identity<T>::type const & lo, /// typename boost::mpl::identity<T>::type const& lo,
/// typename boost::mpl::identity<T>::type const & hi ) /// typename boost::mpl::identity<T>::type const& hi )
/// \return the value "val" brought into the range [ lo, hi ]. /// \return the value "val" brought into the range [ lo, hi ].
/// If the value is less than lo, return lo. /// If the value is less than lo, return lo.
/// If the value is greater than "hi", return hi. /// If the value is greater than "hi", return hi.
@@ -76,8 +76,8 @@ namespace boost { namespace algorithm {
} }
/// \fn clamp_range ( InputIterator first, InputIterator last, OutputIterator out, /// \fn clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
/// std::iterator_traits<InputIterator>::value_type const & lo, /// std::iterator_traits<InputIterator>::value_type lo,
/// std::iterator_traits<InputIterator>::value_type const & hi ) /// std::iterator_traits<InputIterator>::value_type hi )
/// \return clamp the sequence of values [first, last) into [ lo, hi ] /// \return clamp the sequence of values [first, last) into [ lo, hi ]
/// ///
/// \param first The start of the range of values /// \param first The start of the range of values
@@ -88,8 +88,8 @@ namespace boost { namespace algorithm {
/// ///
template<typename InputIterator, typename OutputIterator> template<typename InputIterator, typename OutputIterator>
OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out, OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
typename std::iterator_traits<InputIterator>::value_type const & lo, typename std::iterator_traits<InputIterator>::value_type lo,
typename std::iterator_traits<InputIterator>::value_type const & hi ) typename std::iterator_traits<InputIterator>::value_type hi )
{ {
// this could also be written with bind and std::transform // this could also be written with bind and std::transform
while ( first != last ) while ( first != last )
@@ -98,8 +98,8 @@ namespace boost { namespace algorithm {
} }
/// \fn clamp_range ( const Range &r, OutputIterator out, /// \fn clamp_range ( const Range &r, OutputIterator out,
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & lo, /// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type lo,
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & hi ) /// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type hi )
/// \return clamp the sequence of values [first, last) into [ lo, hi ] /// \return clamp the sequence of values [first, last) into [ lo, hi ]
/// ///
/// \param r The range of values to be clamped /// \param r The range of values to be clamped
@@ -110,16 +110,16 @@ namespace boost { namespace algorithm {
template<typename Range, typename OutputIterator> template<typename Range, typename OutputIterator>
typename boost::disable_if_c<boost::is_same<Range, OutputIterator>::value, OutputIterator>::type typename boost::disable_if_c<boost::is_same<Range, OutputIterator>::value, OutputIterator>::type
clamp_range ( const Range &r, OutputIterator out, clamp_range ( const Range &r, OutputIterator out,
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & lo, typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type lo,
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & hi ) typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type hi )
{ {
return clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi ); return clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi );
} }
/// \fn clamp_range ( InputIterator first, InputIterator last, OutputIterator out, /// \fn clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
/// std::iterator_traits<InputIterator>::value_type const & lo, /// std::iterator_traits<InputIterator>::value_type lo,
/// std::iterator_traits<InputIterator>::value_type const & hi, Pred p ) /// std::iterator_traits<InputIterator>::value_type hi, Pred p )
/// \return clamp the sequence of values [first, last) into [ lo, hi ] /// \return clamp the sequence of values [first, last) into [ lo, hi ]
/// using the comparison predicate p. /// using the comparison predicate p.
/// ///
@@ -134,8 +134,8 @@ namespace boost { namespace algorithm {
/// ///
template<typename InputIterator, typename OutputIterator, typename Pred> template<typename InputIterator, typename OutputIterator, typename Pred>
OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out, OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
typename std::iterator_traits<InputIterator>::value_type const & lo, typename std::iterator_traits<InputIterator>::value_type lo,
typename std::iterator_traits<InputIterator>::value_type const & hi, Pred p ) typename std::iterator_traits<InputIterator>::value_type hi, Pred p )
{ {
// this could also be written with bind and std::transform // this could also be written with bind and std::transform
while ( first != last ) while ( first != last )
@@ -144,8 +144,8 @@ namespace boost { namespace algorithm {
} }
/// \fn clamp_range ( const Range &r, OutputIterator out, /// \fn clamp_range ( const Range &r, OutputIterator out,
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & lo, /// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type lo,
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & hi, /// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type hi,
/// Pred p ) /// Pred p )
/// \return clamp the sequence of values [first, last) into [ lo, hi ] /// \return clamp the sequence of values [first, last) into [ lo, hi ]
/// using the comparison predicate p. /// using the comparison predicate p.
@@ -162,8 +162,8 @@ namespace boost { namespace algorithm {
template<typename Range, typename OutputIterator, typename Pred> template<typename Range, typename OutputIterator, typename Pred>
typename boost::disable_if_c<boost::is_same<Range, OutputIterator>::value, OutputIterator>::type typename boost::disable_if_c<boost::is_same<Range, OutputIterator>::value, OutputIterator>::type
clamp_range ( const Range &r, OutputIterator out, clamp_range ( const Range &r, OutputIterator out,
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & lo, typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type lo,
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & hi, typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type hi,
Pred p ) Pred p )
{ {
return clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi, p ); return clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi, p );

View File

@@ -18,6 +18,10 @@
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of all_of if it is available
using std::all_of; // Section 25.2.1
#else
/// \fn all_of ( InputIterator first, InputIterator last, Predicate p ) /// \fn all_of ( InputIterator first, InputIterator last, Predicate p )
/// \return true if all elements in [first, last) satisfy the predicate 'p' /// \return true if all elements in [first, last) satisfy the predicate 'p'
/// \note returns true on an empty range /// \note returns true on an empty range
@@ -37,6 +41,7 @@ bool all_of ( InputIterator first, InputIterator last, Predicate p )
return false; return false;
return true; return true;
} }
#endif
/// \fn all_of ( const Range &r, Predicate p ) /// \fn all_of ( const Range &r, Predicate p )
/// \return true if all elements in the range satisfy the predicate 'p' /// \return true if all elements in the range satisfy the predicate 'p'

View File

@@ -20,6 +20,10 @@
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
// Use the C++11 versions of any_of if it is available
#if __cplusplus >= 201103L
using std::any_of; // Section 25.2.2
#else
/// \fn any_of ( InputIterator first, InputIterator last, Predicate p ) /// \fn any_of ( InputIterator first, InputIterator last, Predicate p )
/// \return true if any of the elements in [first, last) satisfy the predicate /// \return true if any of the elements in [first, last) satisfy the predicate
/// \note returns false on an empty range /// \note returns false on an empty range
@@ -36,6 +40,7 @@ bool any_of ( InputIterator first, InputIterator last, Predicate p )
return true; return true;
return false; return false;
} }
#endif
/// \fn any_of ( const Range &r, Predicate p ) /// \fn any_of ( const Range &r, Predicate p )
/// \return true if any elements in the range satisfy the predicate 'p' /// \return true if any elements in the range satisfy the predicate 'p'

View File

@@ -18,6 +18,10 @@
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of copy_if if it is available
using std::copy_if; // Section 25.3.1
#else
/// \fn copy_if ( InputIterator first, InputIterator last, OutputIterator result, Predicate p ) /// \fn copy_if ( InputIterator first, InputIterator last, OutputIterator result, Predicate p )
/// \brief Copies all the elements from the input range that satisfy the /// \brief Copies all the elements from the input range that satisfy the
/// predicate to the output range. /// predicate to the output range.
@@ -38,6 +42,7 @@ OutputIterator copy_if ( InputIterator first, InputIterator last, OutputIterator
*result++ = *first; *result++ = *first;
return result; return result;
} }
#endif
/// \fn copy_if ( const Range &r, OutputIterator result, Predicate p ) /// \fn copy_if ( const Range &r, OutputIterator result, Predicate p )
/// \brief Copies all the elements from the input range that satisfy the /// \brief Copies all the elements from the input range that satisfy the

View File

@@ -16,6 +16,10 @@
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of copy_n if it is available
using std::copy_n; // Section 25.3.1
#else
/// \fn copy_n ( InputIterator first, Size n, OutputIterator result ) /// \fn copy_n ( InputIterator first, Size n, OutputIterator result )
/// \brief Copies exactly n (n > 0) elements from the range starting at first to /// \brief Copies exactly n (n > 0) elements from the range starting at first to
/// the range starting at result. /// the range starting at result.
@@ -34,6 +38,7 @@ OutputIterator copy_n ( InputIterator first, Size n, OutputIterator result )
*result = *first; *result = *first;
return result; return result;
} }
#endif
}} // namespace boost and algorithm }} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_COPY_IF_HPP #endif // BOOST_ALGORITHM_COPY_IF_HPP

View File

@@ -19,6 +19,10 @@
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of find_if_not if it is available
using std::find_if_not; // Section 25.2.5
#else
/// \fn find_if_not(InputIterator first, InputIterator last, Predicate p) /// \fn find_if_not(InputIterator first, InputIterator last, Predicate p)
/// \brief Finds the first element in the sequence that does not satisfy the predicate. /// \brief Finds the first element in the sequence that does not satisfy the predicate.
/// \return The iterator pointing to the desired element. /// \return The iterator pointing to the desired element.
@@ -37,6 +41,7 @@ InputIterator find_if_not ( InputIterator first, InputIterator last, Predicate p
break; break;
return first; return first;
} }
#endif
/// \fn find_if_not ( const Range &r, Predicate p ) /// \fn find_if_not ( const Range &r, Predicate p )
/// \brief Finds the first element in the sequence that does not satisfy the predicate. /// \brief Finds the first element in the sequence that does not satisfy the predicate.

View File

@@ -19,6 +19,10 @@
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of iota if it is available
using std::iota; // Section 26.7.6
#else
/// \fn iota ( ForwardIterator first, ForwardIterator last, T value ) /// \fn iota ( ForwardIterator first, ForwardIterator last, T value )
/// \brief Generates an increasing sequence of values, and stores them in [first, last) /// \brief Generates an increasing sequence of values, and stores them in [first, last)
/// ///
@@ -34,6 +38,7 @@ void iota ( ForwardIterator first, ForwardIterator last, T value )
for ( ; first != last; ++first, ++value ) for ( ; first != last; ++first, ++value )
*first = value; *first = value;
} }
#endif
/// \fn iota ( Range &r, T value ) /// \fn iota ( Range &r, T value )
/// \brief Generates an increasing sequence of values, and stores them in the input Range. /// \brief Generates an increasing sequence of values, and stores them in the input Range.

View File

@@ -19,6 +19,10 @@
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of is_partitioned if it is available
using std::is_partitioned; // Section 25.3.13
#else
/// \fn is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p ) /// \fn is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p )
/// \brief Tests to see if a sequence is partitioned according to a predicate /// \brief Tests to see if a sequence is partitioned according to a predicate
/// ///
@@ -41,6 +45,7 @@ bool is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p
return false; return false;
return true; return true;
} }
#endif
/// \fn is_partitioned ( const Range &r, UnaryPredicate p ) /// \fn is_partitioned ( const Range &r, UnaryPredicate p )
/// \brief Generates an increasing sequence of values, and stores them in the input Range. /// \brief Generates an increasing sequence of values, and stores them in the input Range.

View File

@@ -9,8 +9,8 @@
/// \brief Is a sequence a permutation of another sequence /// \brief Is a sequence a permutation of another sequence
/// \author Marshall Clow /// \author Marshall Clow
#ifndef BOOST_ALGORITHM_IS_PERMUTATION11_HPP #ifndef BOOST_ALGORITHM_IS_PERMUTATION_HPP
#define BOOST_ALGORITHM_IS_PERMUTATION11_HPP #define BOOST_ALGORITHM_IS_PERMUTATION_HPP
#include <algorithm> // for std::less, tie, mismatch and is_permutation (if available) #include <algorithm> // for std::less, tie, mismatch and is_permutation (if available)
#include <utility> // for std::make_pair #include <utility> // for std::make_pair
@@ -99,6 +99,11 @@ namespace detail {
} }
/// \endcond /// \endcond
#if __cplusplus >= 201103L
// Use the C++11 versions of is_permutation if it is available
using std::is_permutation; // Section 25.2.12
#else
/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2, BinaryPredicate p ) /// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2, BinaryPredicate p )
/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2 /// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
/// ///
@@ -156,6 +161,58 @@ bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIt
return true; return true;
} }
#endif
/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last,
/// ForwardIterator2 first2, ForwardIterator2 last2 )
/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
///
/// \param first1 The start of the input sequence
/// \param last2 One past the end of the input sequence
/// \param first2 The start of the second sequence
/// \param last1 One past the end of the second sequence
/// \note This function is part of the C++2011 standard library.
/// We will use the standard one if it is available,
/// otherwise we have our own implementation.
template< class ForwardIterator1, class ForwardIterator2 >
bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2 )
{
// How should I deal with the idea that ForwardIterator1::value_type
// and ForwardIterator2::value_type could be different? Define my own comparison predicate?
return boost::algorithm::detail::is_permutation_tag (
first1, last1, first2, last2,
std::equal_to<typename std::iterator_traits<ForwardIterator1>::value_type> (),
typename std::iterator_traits<ForwardIterator1>::iterator_category (),
typename std::iterator_traits<ForwardIterator2>::iterator_category ());
}
/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last,
/// ForwardIterator2 first2, ForwardIterator2 last2,
/// BinaryPredicate p )
/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
///
/// \param first1 The start of the input sequence
/// \param last1 One past the end of the input sequence
/// \param first2 The start of the second sequence
/// \param last2 One past the end of the second sequence
/// \param pred The predicate to compare elements with
///
/// \note This function is part of the C++2011 standard library.
/// We will use the standard one if it is available,
/// otherwise we have our own implementation.
template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate >
bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2,
BinaryPredicate pred )
{
return boost::algorithm::detail::is_permutation_tag (
first1, last1, first2, last2, pred,
typename std::iterator_traits<ForwardIterator1>::iterator_category (),
typename std::iterator_traits<ForwardIterator2>::iterator_category ());
}
/// \fn is_permutation ( const Range &r, ForwardIterator first2 ) /// \fn is_permutation ( const Range &r, ForwardIterator first2 )
/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2 /// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
@@ -186,4 +243,4 @@ is_permutation ( const Range &r, ForwardIterator first2, BinaryPredicate pred )
}} }}
#endif // BOOST_ALGORITHM_IS_PERMUTATION11_HPP #endif // BOOST_ALGORITHM_IS_PERMUTATION_HPP

View File

@@ -26,6 +26,11 @@
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of is_sorted/is_sorted_until if they are available
using std::is_sorted_until; // Section 25.4.1.5
using std::is_sorted; // Section 25.4.1.5
#else
/// \fn is_sorted_until ( ForwardIterator first, ForwardIterator last, Pred p ) /// \fn is_sorted_until ( ForwardIterator first, ForwardIterator last, Pred p )
/// \return the point in the sequence [first, last) where the elements are unordered /// \return the point in the sequence [first, last) where the elements are unordered
/// (according to the comparison predicate 'p'). /// (according to the comparison predicate 'p').
@@ -86,6 +91,7 @@ namespace boost { namespace algorithm {
{ {
return boost::algorithm::is_sorted_until (first, last) == last; return boost::algorithm::is_sorted_until (first, last) == last;
} }
#endif
/// ///
/// -- Range based versions of the C++11 functions /// -- Range based versions of the C++11 functions

View File

@@ -18,6 +18,10 @@
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
// Use the C++11 versions of the none_of if it is available
#if __cplusplus >= 201103L
using std::none_of; // Section 25.2.3
#else
/// \fn none_of ( InputIterator first, InputIterator last, Predicate p ) /// \fn none_of ( InputIterator first, InputIterator last, Predicate p )
/// \return true if none of the elements in [first, last) satisfy the predicate 'p' /// \return true if none of the elements in [first, last) satisfy the predicate 'p'
/// \note returns true on an empty range /// \note returns true on an empty range
@@ -34,6 +38,7 @@ for ( ; first != last; ++first )
return false; return false;
return true; return true;
} }
#endif
/// \fn none_of ( const Range &r, Predicate p ) /// \fn none_of ( const Range &r, Predicate p )
/// \return true if none of the elements in the range satisfy the predicate 'p' /// \return true if none of the elements in the range satisfy the predicate 'p'

View File

@@ -20,6 +20,10 @@
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of partition_copy if it is available
using std::partition_copy; // Section 25.3.13
#else
/// \fn partition_copy ( InputIterator first, InputIterator last, /// \fn partition_copy ( InputIterator first, InputIterator last,
/// OutputIterator1 out_true, OutputIterator2 out_false, UnaryPredicate p ) /// OutputIterator1 out_true, OutputIterator2 out_false, UnaryPredicate p )
/// \brief Copies the elements that satisfy the predicate p from the range [first, last) /// \brief Copies the elements that satisfy the predicate p from the range [first, last)
@@ -49,6 +53,7 @@ partition_copy ( InputIterator first, InputIterator last,
*out_false++ = *first; *out_false++ = *first;
return std::pair<OutputIterator1, OutputIterator2> ( out_true, out_false ); return std::pair<OutputIterator1, OutputIterator2> ( out_true, out_false );
} }
#endif
/// \fn partition_copy ( const Range &r, /// \fn partition_copy ( const Range &r,
/// OutputIterator1 out_true, OutputIterator2 out_false, UnaryPredicate p ) /// OutputIterator1 out_true, OutputIterator2 out_false, UnaryPredicate p )

View File

@@ -19,6 +19,10 @@
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of partition_point if it is available
using std::partition_point; // Section 25.3.13
#else
/// \fn partition_point ( ForwardIterator first, ForwardIterator last, Predicate p ) /// \fn partition_point ( ForwardIterator first, ForwardIterator last, Predicate p )
/// \brief Given a partitioned range, returns the partition point, i.e, the first element /// \brief Given a partitioned range, returns the partition point, i.e, the first element
/// that does not satisfy p /// that does not satisfy p
@@ -48,6 +52,7 @@ ForwardIterator partition_point ( ForwardIterator first, ForwardIterator last, P
} }
return first; return first;
} }
#endif
/// \fn partition_point ( Range &r, Predicate p ) /// \fn partition_point ( Range &r, Predicate p )
/// \brief Given a partitioned range, returns the partition point /// \brief Given a partitioned range, returns the partition point
@@ -56,7 +61,7 @@ ForwardIterator partition_point ( ForwardIterator first, ForwardIterator last, P
/// \param p The predicate to test the values with /// \param p The predicate to test the values with
/// ///
template <typename Range, typename Predicate> template <typename Range, typename Predicate>
typename boost::range_iterator<Range>::type partition_point ( Range &r, Predicate p ) typename boost::range_iterator<Range> partition_point ( Range &r, Predicate p )
{ {
return boost::algorithm::partition_point (boost::begin(r), boost::end(r), p); return boost::algorithm::partition_point (boost::begin(r), boost::end(r), p);
} }

View File

@@ -12,41 +12,41 @@
#ifndef BOOST_ALGORITHM_EQUAL_HPP #ifndef BOOST_ALGORITHM_EQUAL_HPP
#define BOOST_ALGORITHM_EQUAL_HPP #define BOOST_ALGORITHM_EQUAL_HPP
#include <algorithm> // for std::equal #include <algorithm> // for std::equal
#include <functional> // for std::equal_to #include <functional> // for std::equal_to
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
namespace detail { namespace detail {
template <class T1, class T2> template <class T1, class T2>
struct eq : public std::binary_function<T1, T2, bool> { struct eq : public std::binary_function<T1, T2, bool> {
bool operator () ( const T1& v1, const T2& v2 ) const { return v1 == v2 ;} bool operator () ( const T1& v1, const T2& v2 ) const { return v1 == v2 ;}
}; };
template <class RandomAccessIterator1, class RandomAccessIterator2, class BinaryPredicate> template <class RandomAccessIterator1, class RandomAccessIterator2, class BinaryPredicate>
bool equal ( RandomAccessIterator1 first1, RandomAccessIterator1 last1, bool equal ( RandomAccessIterator1 first1, RandomAccessIterator1 last1,
RandomAccessIterator2 first2, RandomAccessIterator2 last2, BinaryPredicate pred, RandomAccessIterator2 first2, RandomAccessIterator2 last2, BinaryPredicate pred,
std::random_access_iterator_tag, std::random_access_iterator_tag ) std::random_access_iterator_tag, std::random_access_iterator_tag )
{ {
// Random-access iterators let is check the sizes in constant time // Random-access iterators let is check the sizes in constant time
if ( std::distance ( first1, last1 ) != std::distance ( first2, last2 )) if ( std::distance ( first1, last1 ) != std::distance ( first2, last2 ))
return false; return false;
// If we know that the sequences are the same size, the original version is fine // If we know that the sequences are the same size, the original version is fine
return std::equal ( first1, last1, first2, pred ); return std::equal ( first1, last1, first2, pred );
} }
template <class InputIterator1, class InputIterator2, class BinaryPredicate> template <class InputIterator1, class InputIterator2, class BinaryPredicate>
bool equal ( InputIterator1 first1, InputIterator1 last1, bool equal ( InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred, InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred,
std::input_iterator_tag, std::input_iterator_tag ) std::input_iterator_tag, std::input_iterator_tag )
{ {
for (; first1 != last1 && first2 != last2; ++first1, ++first2 ) for (; first1 != last1 && first2 != last2; ++first1, ++first2 )
if ( !pred(*first1, *first2 )) if ( !pred(*first1, *first2 ))
return false; return false;
return first1 == last1 && first2 == last2; return first1 == last1 && first2 == last2;
} }
} }
/// \fn equal ( InputIterator1 first1, InputIterator1 last1, /// \fn equal ( InputIterator1 first1, InputIterator1 last1,
@@ -63,10 +63,10 @@ template <class InputIterator1, class InputIterator2, class BinaryPredicate>
bool equal ( InputIterator1 first1, InputIterator1 last1, bool equal ( InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred ) InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred )
{ {
return boost::algorithm::detail::equal ( return boost::algorithm::detail::equal (
first1, last1, first2, last2, pred, first1, last1, first2, last2, pred,
typename std::iterator_traits<InputIterator1>::iterator_category (), typename std::iterator_traits<InputIterator1>::iterator_category (),
typename std::iterator_traits<InputIterator2>::iterator_category ()); typename std::iterator_traits<InputIterator2>::iterator_category ());
} }
/// \fn equal ( InputIterator1 first1, InputIterator1 last1, /// \fn equal ( InputIterator1 first1, InputIterator1 last1,
@@ -81,16 +81,16 @@ template <class InputIterator1, class InputIterator2>
bool equal ( InputIterator1 first1, InputIterator1 last1, bool equal ( InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2 ) InputIterator2 first2, InputIterator2 last2 )
{ {
return boost::algorithm::detail::equal ( return boost::algorithm::detail::equal (
first1, last1, first2, last2, first1, last1, first2, last2,
boost::algorithm::detail::eq< boost::algorithm::detail::eq<
typename std::iterator_traits<InputIterator1>::value_type, typename std::iterator_traits<InputIterator1>::value_type,
typename std::iterator_traits<InputIterator2>::value_type> (), typename std::iterator_traits<InputIterator2>::value_type> (),
typename std::iterator_traits<InputIterator1>::iterator_category (), typename std::iterator_traits<InputIterator1>::iterator_category (),
typename std::iterator_traits<InputIterator2>::iterator_category ()); typename std::iterator_traits<InputIterator2>::iterator_category ());
} }
// There are already range-based versions of these. // There are already range-based versions of these.
}} // namespace boost and algorithm }} // namespace boost and algorithm

View File

@@ -1,84 +0,0 @@
/*
Copyright (c) Marshall Clow 2014.
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)
*/
/// \file is_permutation.hpp
/// \brief Is a sequence a permutation of another sequence (four iterator versions)
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_IS_PERMUTATION14_HPP
#define BOOST_ALGORITHM_IS_PERMUTATION14_HPP
#include <algorithm> // for std::less, tie, mismatch and is_permutation (if available)
#include <utility> // for std::make_pair
#include <functional> // for std::equal_to
#include <iterator>
#include <boost/algorithm/cxx11/is_permutation.hpp>
#include <boost/algorithm/cxx14/mismatch.hpp>
namespace boost { namespace algorithm {
/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last,
/// ForwardIterator2 first2, ForwardIterator2 last2 )
/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
///
/// \param first1 The start of the input sequence
/// \param last2 One past the end of the input sequence
/// \param first2 The start of the second sequence
/// \param last1 One past the end of the second sequence
/// \note This function is part of the C++2014 standard library.
/// We will use the standard one if it is available,
/// otherwise we have our own implementation.
template< class ForwardIterator1, class ForwardIterator2 >
bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2 )
{
// How should I deal with the idea that ForwardIterator1::value_type
// and ForwardIterator2::value_type could be different? Define my own comparison predicate?
std::pair<ForwardIterator1, ForwardIterator2> eq = boost::algorithm::mismatch
( first1, last1, first2, last2 );
if ( eq.first == last1 && eq.second == last2)
return true;
return boost::algorithm::detail::is_permutation_tag (
eq.first, last1, eq.second, last2,
std::equal_to<typename std::iterator_traits<ForwardIterator1>::value_type> (),
typename std::iterator_traits<ForwardIterator1>::iterator_category (),
typename std::iterator_traits<ForwardIterator2>::iterator_category ());
}
/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last,
/// ForwardIterator2 first2, ForwardIterator2 last2,
/// BinaryPredicate p )
/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
///
/// \param first1 The start of the input sequence
/// \param last1 One past the end of the input sequence
/// \param first2 The start of the second sequence
/// \param last2 One past the end of the second sequence
/// \param pred The predicate to compare elements with
///
/// \note This function is part of the C++2014 standard library.
/// We will use the standard one if it is available,
/// otherwise we have our own implementation.
template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate >
bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2,
BinaryPredicate pred )
{
std::pair<ForwardIterator1, ForwardIterator2> eq = boost::algorithm::mismatch
( first1, last1, first2, last2, pred );
if ( eq.first == last1 && eq.second == last2)
return true;
return boost::algorithm::detail::is_permutation_tag (
first1, last1, first2, last2, pred,
typename std::iterator_traits<ForwardIterator1>::iterator_category (),
typename std::iterator_traits<ForwardIterator2>::iterator_category ());
}
}}
#endif // BOOST_ALGORITHM_IS_PERMUTATION14_HPP

View File

@@ -12,8 +12,8 @@
#ifndef BOOST_ALGORITHM_MISMATCH_HPP #ifndef BOOST_ALGORITHM_MISMATCH_HPP
#define BOOST_ALGORITHM_MISMATCH_HPP #define BOOST_ALGORITHM_MISMATCH_HPP
#include <algorithm> // for std::mismatch #include <algorithm> // for std::mismatch
#include <utility> // for std::pair #include <utility> // for std::pair
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
@@ -29,9 +29,9 @@ namespace boost { namespace algorithm {
/// \param pred A predicate for comparing the elements of the ranges /// \param pred A predicate for comparing the elements of the ranges
template <class InputIterator1, class InputIterator2, class BinaryPredicate> template <class InputIterator1, class InputIterator2, class BinaryPredicate>
std::pair<InputIterator1, InputIterator2> mismatch ( std::pair<InputIterator1, InputIterator2> mismatch (
InputIterator1 first1, InputIterator1 last1, InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2, InputIterator2 first2, InputIterator2 last2,
BinaryPredicate pred ) BinaryPredicate pred )
{ {
for (; first1 != last1 && first2 != last2; ++first1, ++first2) for (; first1 != last1 && first2 != last2; ++first1, ++first2)
if ( !pred ( *first1, *first2 )) if ( !pred ( *first1, *first2 ))
@@ -49,8 +49,8 @@ std::pair<InputIterator1, InputIterator2> mismatch (
/// \param last2 One past the end of the second range. /// \param last2 One past the end of the second range.
template <class InputIterator1, class InputIterator2> template <class InputIterator1, class InputIterator2>
std::pair<InputIterator1, InputIterator2> mismatch ( std::pair<InputIterator1, InputIterator2> mismatch (
InputIterator1 first1, InputIterator1 last1, InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2 ) InputIterator2 first2, InputIterator2 last2 )
{ {
for (; first1 != last1 && first2 != last2; ++first1, ++first2) for (; first1 != last1 && first2 != last2; ++first1, ++first2)
if ( *first1 != *first2 ) if ( *first1 != *first2 )
@@ -58,7 +58,7 @@ std::pair<InputIterator1, InputIterator2> mismatch (
return std::pair<InputIterator1, InputIterator2>(first1, first2); return std::pair<InputIterator1, InputIterator2>(first1, first2);
} }
// There are already range-based versions of these. // There are already range-based versions of these.
}} // namespace boost and algorithm }} // namespace boost and algorithm

View File

@@ -207,6 +207,7 @@ OutputIterator unhex ( InputIterator first, InputIterator last, OutputIterator o
/// \note Based on the MySQL function of the same name /// \note Based on the MySQL function of the same name
template <typename T, typename OutputIterator> template <typename T, typename OutputIterator>
OutputIterator unhex ( const T *ptr, OutputIterator out ) { OutputIterator unhex ( const T *ptr, OutputIterator out ) {
typedef typename detail::hex_iterator_traits<OutputIterator>::value_type OutputType;
// If we run into the terminator while decoding, we will throw a // If we run into the terminator while decoding, we will throw a
// malformed input exception. It would be nicer to throw a 'Not enough input' // malformed input exception. It would be nicer to throw a 'Not enough input'
// exception - but how much extra work would that require? // exception - but how much extra work would that require?

View File

@@ -21,7 +21,7 @@
#include <boost/array.hpp> #include <boost/array.hpp>
#ifdef BOOST_NO_CXX11_HDR_UNORDERED_MAP #ifdef BOOST_NO_CXX11_HDR_UNORDERED_MAP
#include <boost/unordered_map.hpp> #include <boost/tr1/tr1/unordered_map>
#else #else
#include <unordered_map> #include <unordered_map>
#endif #endif
@@ -40,7 +40,7 @@ namespace boost { namespace algorithm { namespace detail {
class skip_table<key_type, value_type, false> { class skip_table<key_type, value_type, false> {
private: private:
#ifdef BOOST_NO_CXX11_HDR_UNORDERED_MAP #ifdef BOOST_NO_CXX11_HDR_UNORDERED_MAP
typedef boost::unordered_map<key_type, value_type> skip_map; typedef std::tr1::unordered_map<key_type, value_type> skip_map;
#else #else
typedef std::unordered_map<key_type, value_type> skip_map; typedef std::unordered_map<key_type, value_type> skip_map;
#endif #endif

View File

@@ -622,6 +622,8 @@ namespace boost {
{ {
#if BOOST_WORKAROUND( __MWERKS__, <= 0x3003 ) #if BOOST_WORKAROUND( __MWERKS__, <= 0x3003 )
return iterator_range<const ForwardIterator2T>(this->m_Range); return iterator_range<const ForwardIterator2T>(this->m_Range);
#elif BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
return iterator_range<ForwardIterator2T>(m_Range.begin(), m_Range.end());
#else #else
return m_Range; return m_Range;
#endif #endif

View File

@@ -132,7 +132,12 @@ namespace boost {
// increment // increment
void increment() void increment()
{ {
m_Match=this->do_find(m_Match.end(),m_End); if(m_Match.begin() == m_Match.end())
m_Match=this->do_find(m_Match.end(),m_End);
else {
input_iterator_type last = m_Match.begin();
m_Match=this->do_find(++last,m_End);
}
} }
// comparison // comparison
@@ -230,12 +235,7 @@ namespace boost {
\post eof()==true \post eof()==true
*/ */
split_iterator() : split_iterator() {}
m_Next(),
m_End(),
m_bEof(true)
{}
//! Copy constructor //! Copy constructor
/*! /*!
Construct a copy of the split_iterator Construct a copy of the split_iterator

View File

@@ -36,6 +36,47 @@ namespace boost {
// sequence traits -----------------------------------------------// // sequence traits -----------------------------------------------//
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
//! Native replace tester
/*!
Declare an override of this tester function with return
type boost::string_algo::yes_type for a sequence with this property.
\return yes_type if the container has basic_string like native replace
method.
*/
no_type has_native_replace_tester(...);
//! Stable iterators tester
/*!
Declare an override of this tester function with return
type boost::string_algo::yes_type for a sequence with this property.
\return yes_type if the sequence's insert/replace/erase methods do not invalidate
existing iterators.
*/
no_type has_stable_iterators_tester(...);
//! const time insert tester
/*!
Declare an override of this tester function with return
type boost::string_algo::yes_type for a sequence with this property.
\return yes_type if the sequence's insert method is working in constant time
*/
no_type has_const_time_insert_tester(...);
//! const time erase tester
/*!
Declare an override of this tester function with return
type boost::string_algo::yes_type for a sequence with this property.
\return yes_type if the sequence's erase method is working in constant time
*/
no_type has_const_time_erase_tester(...);
#endif //BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
//! Native replace trait //! Native replace trait
/*! /*!
@@ -45,12 +86,20 @@ namespace boost {
class has_native_replace class has_native_replace
{ {
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
private:
static T* t;
public:
BOOST_STATIC_CONSTANT(bool, value=(
sizeof(has_native_replace_tester(t))==sizeof(yes_type) ) );
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
public: public:
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) # if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = false }; enum { value = false };
# else # else
BOOST_STATIC_CONSTANT(bool, value=false); BOOST_STATIC_CONSTANT(bool, value=false);
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) # endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
typedef mpl::bool_<has_native_replace<T>::value> type; typedef mpl::bool_<has_native_replace<T>::value> type;
@@ -65,12 +114,20 @@ namespace boost {
template< typename T > template< typename T >
class has_stable_iterators class has_stable_iterators
{ {
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
private:
static T* t;
public:
BOOST_STATIC_CONSTANT(bool, value=(
sizeof(has_stable_iterators_tester(t))==sizeof(yes_type) ) );
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
public: public:
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) # if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = false }; enum { value = false };
# else # else
BOOST_STATIC_CONSTANT(bool, value=false); BOOST_STATIC_CONSTANT(bool, value=false);
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) # endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
typedef mpl::bool_<has_stable_iterators<T>::value> type; typedef mpl::bool_<has_stable_iterators<T>::value> type;
}; };
@@ -84,12 +141,20 @@ namespace boost {
template< typename T > template< typename T >
class has_const_time_insert class has_const_time_insert
{ {
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
private:
static T* t;
public:
BOOST_STATIC_CONSTANT(bool, value=(
sizeof(has_const_time_insert_tester(t))==sizeof(yes_type) ) );
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
public: public:
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) # if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = false }; enum { value = false };
# else # else
BOOST_STATIC_CONSTANT(bool, value=false); BOOST_STATIC_CONSTANT(bool, value=false);
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) # endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
typedef mpl::bool_<has_const_time_insert<T>::value> type; typedef mpl::bool_<has_const_time_insert<T>::value> type;
}; };
@@ -103,12 +168,20 @@ namespace boost {
template< typename T > template< typename T >
class has_const_time_erase class has_const_time_erase
{ {
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
private:
static T* t;
public:
BOOST_STATIC_CONSTANT(bool, value=(
sizeof(has_const_time_erase_tester(t))==sizeof(yes_type) ) );
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
public: public:
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) # if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = false }; enum { value = false };
# else # else
BOOST_STATIC_CONSTANT(bool, value=false); BOOST_STATIC_CONSTANT(bool, value=false);
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) # endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
typedef mpl::bool_<has_const_time_erase<T>::value> type; typedef mpl::bool_<has_const_time_erase<T>::value> type;
}; };

View File

@@ -20,6 +20,22 @@ namespace boost {
// std::list<> traits -----------------------------------------------// // std::list<> traits -----------------------------------------------//
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// stable iterators tester
template<typename T, typename AllocT>
yes_type has_stable_iterators_tester( const ::std::list<T,AllocT>* );
// const time insert tester
template<typename T, typename AllocT>
yes_type has_const_time_insert_tester( const ::std::list<T,AllocT>* );
// const time erase tester
template<typename T, typename AllocT>
yes_type has_const_time_erase_tester( const ::std::list<T,AllocT>* );
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// stable iterators trait // stable iterators trait
template<typename T, typename AllocT> template<typename T, typename AllocT>
@@ -59,6 +75,7 @@ namespace boost {
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) #endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_const_time_erase<T>::value> type; typedef mpl::bool_<has_const_time_erase<T>::value> type;
}; };
#endif
} // namespace algorithm } // namespace algorithm

View File

@@ -20,6 +20,25 @@ namespace boost {
// SGI's std::rope<> traits -----------------------------------------------// // SGI's std::rope<> traits -----------------------------------------------//
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// native replace tester
template<typename T, typename TraitsT, typename AllocT>
yes_type has_native_replace_tester( const std::rope<T, TraitsT, AllocT>* );
// stable iterators tester
template<typename T, typename TraitsT, typename AllocT>
yes_type has_stable_iterators_tester( const std::rope<T, TraitsT, AllocT>* );
// const time insert tester
template<typename T, typename TraitsT, typename AllocT>
yes_type has_const_time_insert_tester( const std::rope<T, TraitsT, AllocT>* );
// const time erase tester
template<typename T, typename TraitsT, typename AllocT>
yes_type has_const_time_erase_tester( const std::rope<T, TraitsT, AllocT>* );
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// native replace trait // native replace trait
template<typename T, typename TraitsT, typename AllocT> template<typename T, typename TraitsT, typename AllocT>
@@ -72,6 +91,7 @@ namespace boost {
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) #endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<value> type; typedef mpl::bool_<value> type;
}; };
#endif
} // namespace algorithm } // namespace algorithm

View File

@@ -21,6 +21,21 @@ namespace boost {
// SGI's std::slist<> traits -----------------------------------------------// // SGI's std::slist<> traits -----------------------------------------------//
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// stable iterators tester
template<typename T, typename AllocT>
yes_type has_stable_iterators_tester( const BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT>* );
// const time insert tester
template<typename T, typename AllocT>
yes_type has_const_time_insert_tester( const BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT>* );
// const time erase tester
template<typename T, typename AllocT>
yes_type has_const_time_erase_tester( const BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT>* );
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// stable iterators trait // stable iterators trait
template<typename T, typename AllocT> template<typename T, typename AllocT>
@@ -60,6 +75,7 @@ namespace boost {
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) #endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_const_time_erase<T>::value> type; typedef mpl::bool_<has_const_time_erase<T>::value> type;
}; };
#endif
} // namespace algorithm } // namespace algorithm

View File

@@ -20,6 +20,13 @@ namespace boost {
// std::basic_string<> traits -----------------------------------------------// // std::basic_string<> traits -----------------------------------------------//
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// native replace tester
template<typename T, typename TraitsT, typename AllocT>
yes_type has_native_replace_tester( const std::basic_string<T, TraitsT, AllocT>* );
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// native replace trait // native replace trait
template<typename T, typename TraitsT, typename AllocT> template<typename T, typename TraitsT, typename AllocT>
@@ -36,6 +43,7 @@ namespace boost {
}; };
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
} // namespace algorithm } // namespace algorithm
} // namespace boost } // namespace boost

View File

@@ -0,0 +1,52 @@
/*
Copyright (c) Marshall Clow 2012.
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)
Alternate interfaces (aka "wrappers") for algorithms.
*/
#ifndef BOOST_ALGORITHM_WRAPPERS_HPP
#define BOOST_ALGORITHM_WRAPPERS_HPP
namespace boost { namespace algorithm {
/// \fn find_ptr ( Container &c, Key k )
/// \return a pointer to the value matching the key in the container,
/// or NULL if the key does not exist in the container.
///
/// \note: This is a wrapper around Container::find, with a useful interface.
/// Suggested by Olaf van der Spek
///
/// \param c The container to be searched
/// \param k The key value to search with
template <class Container, class Key>
typename Container::value_type::second_type*
find_ptr ( Container &c, Key k )
{
typename Container::iterator iter = c.find ( k );
return iter == c.end() ? NULL : &iter->second;
}
/// \fn find_ptr ( const Container &c, Key k )
/// \return a pointer to the value matching the key in the container,
/// or NULL if the key does not exist in the container.
///
/// \note: This is a wrapper around Container::find, with a useful interface.
/// Suggested by Olaf van der Spek
///
/// \param c The container to be searched
/// \param k The key value to search with
template <class Container, class Key>
const typename Container::value_type::second_type*
find_ptr ( const Container &c, Key k )
{
typename Container::const_iterator iter = c.find ( k );
return iter == c.end() ? NULL : &iter->second;
}
}}
#endif

View File

@@ -1,47 +0,0 @@
[
{
"key": "algorithm",
"name": "Algorithm",
"authors": [
"Marshall Clow"
],
"description": "A collection of useful generic algorithms.",
"category": [
"Algorithms"
],
"maintainers": [
"Marshall Clow <marshall -at- idio.com>"
]
},
{
"key": "algorithm/minmax",
"name": "Min-Max",
"authors": [
"Hervé Brönnimann"
],
"description": "Standard library extensions for simultaneous min/max and min/max element computations.",
"documentation": "minmax/",
"category": [
"Algorithms"
],
"maintainers": [
"Marshall Clow <marshall -at- idio.com>"
]
},
{
"key": "algorithm/string",
"name": "String Algo",
"authors": [
"Pavol Droba"
],
"description": "String algorithms library.",
"documentation": "string/",
"category": [
"Algorithms",
"String"
],
"maintainers": [
"Marshall Clow <marshall -at- idio.com>"
]
}
]

View File

@@ -181,21 +181,6 @@ void find_test()
( (cv_result.begin()-str1.begin()) == 3) && ( (cv_result.begin()-str1.begin()) == 3) &&
( (cv_result.end()-str1.begin()) == 6) ); ( (cv_result.end()-str1.begin()) == 6) );
string s1("abc def ghi jkl");
find_iterator<string::iterator> fEnd;
find_iterator<string::iterator> fxIt = make_find_iterator(s1,
token_finder(is_alnum(), token_compress_on));
BOOST_CHECK((fxIt != fEnd) && (*fxIt == string("abc")));
++fxIt;
BOOST_CHECK((fxIt != fEnd) && (*fxIt == string("def")));
++fxIt;
BOOST_CHECK((fxIt != fEnd) && (*fxIt == string("ghi")));
++fxIt;
BOOST_CHECK((fxIt != fEnd) && (*fxIt == string("jkl")));
++fxIt;
BOOST_CHECK(fxIt == fEnd);
nc_result=find_token( str1, is_any_of("abc"), token_compress_off ); nc_result=find_token( str1, is_any_of("abc"), token_compress_off );
BOOST_CHECK( BOOST_CHECK(
( (nc_result.begin()-str1.begin()) == 3) && ( (nc_result.begin()-str1.begin()) == 3) &&
@@ -266,6 +251,19 @@ void find_test()
osstr << find_first( str1, "abc" ); osstr << find_first( str1, "abc" );
BOOST_CHECK( osstr.str()=="abc" ); BOOST_CHECK( osstr.str()=="abc" );
// Empty string test
BOOST_TEST_CHECKPOINT( "overlapping" );
std::string overlap_target("aaaa");
std::vector<boost::iterator_range<std::string::iterator> > overlap_results;
boost::algorithm::find_all(overlap_results, overlap_target, string("aaa"));
BOOST_CHECK( overlap_results.size() == 2 );
std::string overlap_target2("aaaabbbbaaaa");
boost::algorithm::find_all(overlap_results, overlap_target2, string("bb"));
BOOST_CHECK( overlap_results.size() == 3 );
boost::algorithm::find_all(overlap_results, overlap_target2, string("aa"));
BOOST_CHECK( overlap_results.size() == 6 );
} }
// test main // test main

View File

@@ -46,7 +46,7 @@ void iterator_test()
const char* pch1="xx-abc--xx-abb"; const char* pch1="xx-abc--xx-abb";
vector<string> tokens; vector<string> tokens;
vector< vector<int> > vtokens; vector< vector<int> > vtokens;
// find_all tests // find_all tests
find_all( find_all(
tokens, tokens,
@@ -182,7 +182,7 @@ void iterator_test()
BOOST_CHECK(siter==split_iterator<string::iterator>()); BOOST_CHECK(siter==split_iterator<string::iterator>());
// Make sure we work with forward iterators // Make sure we work with forward iterators
// See bug #7989 // See bug #7989
list<char> l1; list<char> l1;
find_iterator<list<char>::iterator> liter=make_find_iterator(l1, first_finder("xx")); find_iterator<list<char>::iterator> liter=make_find_iterator(l1, first_finder("xx"));
} }

7
test/Jamfile.v2 Normal file → Executable file
View File

@@ -27,10 +27,8 @@ alias unit_test_framework
[ compile-fail search_fail2.cpp : : : : ] [ compile-fail search_fail2.cpp : : : : ]
[ compile-fail search_fail3.cpp : : : : ] [ compile-fail search_fail3.cpp : : : : ]
# Misc tests # Clamp tests
[ run clamp_test.cpp unit_test_framework : : : : clamp_test ] [ run clamp_test.cpp unit_test_framework : : : : clamp_test ]
[ run power_test.cpp unit_test_framework : : : : power_test ]
[ compile-fail power_fail1.cpp : : : : ]
# Cxx11 tests # Cxx11 tests
[ run all_of_test.cpp unit_test_framework : : : : all_of_test ] [ run all_of_test.cpp unit_test_framework : : : : all_of_test ]
@@ -60,6 +58,9 @@ alias unit_test_framework
[ run hex_test4.cpp unit_test_framework : : : : hex_test4 ] [ run hex_test4.cpp unit_test_framework : : : : hex_test4 ]
[ compile-fail hex_fail1.cpp ] [ compile-fail hex_fail1.cpp ]
# Wrapper tests
[ run wrapper_test1.cpp unit_test_framework : : : : wrapper_test1 ]
# Gather tests # Gather tests
[ run gather_test1.cpp unit_test_framework : : : : gather_test1 ] [ run gather_test1.cpp unit_test_framework : : : : gather_test1 ]
[ compile-fail gather_fail1.cpp ] [ compile-fail gather_fail1.cpp ]

0
test/clamp_test.cpp Normal file → Executable file
View File

0
test/empty_search_test.cpp Normal file → Executable file
View File

View File

@@ -11,7 +11,6 @@
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/algorithm/cxx11/is_permutation.hpp> #include <boost/algorithm/cxx11/is_permutation.hpp>
#include <boost/algorithm/cxx14/is_permutation.hpp>
#define BOOST_TEST_MAIN #define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>

View File

@@ -1,21 +1,12 @@
/*
Copyright (c) Marshall Clow 2013.
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)
For more information, see http://www.boost.org
*/
#ifndef ITERATOR_TEST_H #ifndef ITERATOR_TEST_H
#define ITERATOR_TEST_H #define ITERATOR_TEST_H
/* /*
A set of iterator adapters for constructing test cases A set of iterator adapters for constructing test cases
From an iterator (or a pointer), you can make any class of iterator. From an iterator (or a pointer), you can make any class of iterator.
Assuming you want to degrade the capabilities. Assuming you want to degrade the capabilities.
Modeled closely on work that Howard Hinnant did for libc++. Modeled closely on work that Howard Hinnant did for libc++.
*/ */
#include <iterator> #include <iterator>
@@ -278,10 +269,10 @@ public:
private: private:
It it_; It it_;
template <typename U> friend class output_iterator; template <typename U> friend class output_iterator;
}; };
// No comparison operators for output iterators // No comparison operators for output iterators
// == Get the base of an iterator; used for comparisons == // == Get the base of an iterator; used for comparisons ==
template <typename Iter> template <typename Iter>
@@ -299,7 +290,7 @@ inline Iter base(bidirectional_iterator<Iter> i) { return i.base(); }
template <typename Iter> template <typename Iter>
inline Iter base(random_access_iterator<Iter> i) { return i.base(); } inline Iter base(random_access_iterator<Iter> i) { return i.base(); }
template <typename Iter> // everything else template <typename Iter> // everything else
inline Iter base(Iter i) { return i; } inline Iter base(Iter i) { return i; }
#endif // ITERATORS_H #endif // ITERATORS_H

View File

@@ -43,17 +43,16 @@ void test_sequence ( Container &v, Predicate comp, int expected ) {
res = ba::partition_point ( v.begin (), v.end (), comp ); res = ba::partition_point ( v.begin (), v.end (), comp );
exp = offset_to_iter ( v, expected ); exp = offset_to_iter ( v, expected );
std::cout << "Expected(1): " << std::distance ( v.begin (), exp )
<< ", got: " << std::distance ( v.begin (), res ) << std::endl;
BOOST_CHECK ( exp == res ); BOOST_CHECK ( exp == res );
// Duplicate the last element; this checks for any even/odd problems // Duplicate the last element; this checks for any even/odd problems
v.push_back ( * v.rbegin ()); v.push_back ( * v.rbegin ());
res = ba::partition_point ( v.begin (), v.end (), comp ); res = ba::partition_point ( v.begin (), v.end (), comp );
exp = offset_to_iter ( v, expected ); exp = offset_to_iter ( v, expected );
BOOST_CHECK ( exp == res ); std::cout << "Expected(2): " << std::distance ( v.begin (), exp )
<< ", got: " << std::distance ( v.begin (), res ) << std::endl;
// Range based test
res = ba::partition_point ( v, comp );
exp = offset_to_iter ( v, expected );
BOOST_CHECK ( exp == res ); BOOST_CHECK ( exp == res );
} }

View File

@@ -1,24 +0,0 @@
/*
Copyright (c) Marshall Clow 2014.
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)
For more information, see http://www.boost.org
*/
#include <iostream>
#include <boost/config.hpp>
#include <boost/algorithm/algorithm.hpp>
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
namespace ba = boost::algorithm;
BOOST_AUTO_TEST_CASE( test_main )
{
// Second argument must be an integral value
BOOST_CHECK ( ba::power(1, 1.0) == 1);
}

View File

@@ -1,35 +0,0 @@
/*
Copyright (c) Marshall Clow 2014.
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)
For more information, see http://www.boost.org
*/
#include <iostream>
#include <boost/config.hpp>
#include <boost/algorithm/algorithm.hpp>
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
namespace ba = boost::algorithm;
BOOST_AUTO_TEST_CASE( test_main )
{
BOOST_CHECK ( ba::power(0, 0) == 1);
BOOST_CHECK ( ba::power(5, 0) == 1);
BOOST_CHECK ( ba::power(1, 1) == 1);
BOOST_CHECK ( ba::power(1, 4) == 1);
BOOST_CHECK ( ba::power(3, 2) == 9);
BOOST_CHECK ( ba::power(2, 3) == 8);
BOOST_CHECK ( ba::power(3, 3) == 27);
BOOST_CHECK ( ba::power(2, 30) == 0x40000000);
BOOST_CHECK ( ba::power(5L, 10) == 3125*3125);
BOOST_CHECK ( ba::power(18, 3) == 18*18*18);
BOOST_CHECK ( ba::power(3,2) == ba::power(3,2, std::multiplies<int>()));
BOOST_CHECK ( ba::power(3,2, std::plus<int>()) == 6);
}

0
test/search_test1.cpp Normal file → Executable file
View File

0
test/search_test2.cpp Normal file → Executable file
View File

0
test/search_test3.cpp Normal file → Executable file
View File

76
test/wrapper_test1.cpp Normal file
View File

@@ -0,0 +1,76 @@
/*
Copyright (c) Marshall Clow 2012.
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)
For more information, see http://www.boost.org
*/
#include <boost/config.hpp>
#include <boost/algorithm/wrappers.hpp>
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
#include <functional>
#include <string>
#include <map>
namespace ba = boost::algorithm;
void test_int ()
{
std::map<int, int> m;
std::multimap<int, int> mm;
int *ptr;
// try with an empty map
BOOST_CHECK ( ba::find_ptr ( m , 3 ) == NULL );
BOOST_CHECK ( ba::find_ptr ( mm, 3 ) == NULL );
m.insert ( std::make_pair <int, int> ( 5, 5 ));
mm.insert ( std::make_pair <int, int> ( 9, 9 ));
BOOST_CHECK ( ba::find_ptr ( m , 3 ) == NULL );
BOOST_CHECK ( ba::find_ptr ( mm, 3 ) == NULL );
ptr = ba::find_ptr ( m, 5 );
BOOST_CHECK ( ptr != NULL && *ptr == 5 );
BOOST_CHECK ( ba::find_ptr ( m , 9 ) == NULL );
ptr = ba::find_ptr ( mm, 9 );
BOOST_CHECK ( ptr != NULL && *ptr == 9 );
BOOST_CHECK ( ba::find_ptr ( mm, 5 ) == NULL );
}
void test_str ()
{
std::map<int, std::string> m;
std::multimap<int, std::string> mm;
std::string *ptr;
// try with an empty map
BOOST_CHECK ( ba::find_ptr ( m , 31 ) == NULL );
BOOST_CHECK ( ba::find_ptr ( mm, 31 ) == NULL );
m.insert ( std::make_pair <int, std::string> ( 55, "fifty-five" ));
mm.insert ( std::make_pair <int, std::string> ( 66, "sixty-six" ));
BOOST_CHECK ( ba::find_ptr ( m , 3 ) == NULL );
BOOST_CHECK ( ba::find_ptr ( mm, 3 ) == NULL );
ptr = ba::find_ptr ( m, 55 );
BOOST_CHECK ( ptr != NULL && *ptr == "fifty-five" );
BOOST_CHECK ( ba::find_ptr ( m , 66 ) == NULL );
ptr = ba::find_ptr ( mm, 66 );
BOOST_CHECK ( ptr != NULL && *ptr == "sixty-six" );
BOOST_CHECK ( ba::find_ptr ( mm, 55 ) == NULL );
}
BOOST_AUTO_TEST_CASE( test_main )
{
test_int ();
test_str ();
}