Compare commits

..

1 Commits

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

View File

@ -22,7 +22,7 @@ Consider the two sequences:
std::equal ( seq1.begin (), seq1.end (), seq2.begin ()); // true
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).

View File

@ -22,7 +22,7 @@ Consider the two sequences:
std::mismatch ( seq1.begin (), seq1.end (), seq2.begin ()); // <3, 3>
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).

View File

@ -19,11 +19,11 @@ The function `is_sorted(sequence)` determines whether or not a sequence is compl
``
namespace boost { namespace algorithm {
template <typename ForwardIterator, typename Pred>
bool is_sorted ( ForwardIterator first, ForwardIterator last, Pred p );
template <typename Iterator, typename Pred>
bool is_sorted ( Iterator first, Iterator last, Pred p );
template <typename ForwardIterator>
bool is_sorted ( ForwardIterator first, ForwardIterator last );
template <typename Iterator>
bool is_sorted ( Iterator first, Iterator last );
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]
@ -88,8 +88,8 @@ To test if a sequence is decreasing (each element no larger than the preceding o
``
namespace boost { namespace algorithm {
template <typename ForwardIterator>
bool is_decreasing ( ForwardIterator first, ForwardIterator last );
template <typename Iterator>
bool is_decreasing ( Iterator first, Iterator last );
template <typename R>
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):
``
namespace boost { namespace algorithm {
template <typename ForwardIterator>
bool is_strictly_increasing ( ForwardIterator first, ForwardIterator last );
template <typename Iterator>
bool is_strictly_increasing ( Iterator first, Iterator last );
template <typename R>
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):
``
namespace boost { namespace algorithm {
template <typename ForwardIterator>
bool is_strictly_decreasing ( ForwardIterator first, ForwardIterator last );
template <typename Iterator>
bool is_strictly_decreasing ( Iterator first, Iterator last );
template <typename R>
bool is_strictly_decreasing ( const R &range );

View File

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

View File

@ -9,8 +9,8 @@
/// \brief Is a sequence a permutation of another sequence
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_IS_PERMUTATION11_HPP
#define BOOST_ALGORITHM_IS_PERMUTATION11_HPP
#ifndef BOOST_ALGORITHM_IS_PERMUTATION_HPP
#define BOOST_ALGORITHM_IS_PERMUTATION_HPP
#include <algorithm> // for std::less, tie, mismatch and is_permutation (if available)
#include <utility> // for std::make_pair
@ -163,6 +163,56 @@ bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIt
#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 )
/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
@ -193,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

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

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)
*/
/// \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 {
#if __cplusplus <= 201103L
/// \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
}}
#endif // BOOST_ALGORITHM_IS_PERMUTATION14_HPP

View File

@ -12,8 +12,8 @@
#ifndef BOOST_ALGORITHM_MISMATCH_HPP
#define BOOST_ALGORITHM_MISMATCH_HPP
#include <algorithm> // for std::mismatch
#include <utility> // for std::pair
#include <algorithm> // for std::mismatch
#include <utility> // for std::pair
namespace boost { namespace algorithm {
@ -29,9 +29,9 @@ namespace boost { namespace algorithm {
/// \param pred A predicate for comparing the elements of the ranges
template <class InputIterator1, class InputIterator2, class BinaryPredicate>
std::pair<InputIterator1, InputIterator2> mismatch (
InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
BinaryPredicate pred )
InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
BinaryPredicate pred )
{
for (; first1 != last1 && first2 != last2; ++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.
template <class InputIterator1, class InputIterator2>
std::pair<InputIterator1, InputIterator2> mismatch (
InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2 )
InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2 )
{
for (; first1 != last1 && first2 != last2; ++first1, ++first2)
if ( *first1 != *first2 )
@ -58,7 +58,7 @@ std::pair<InputIterator1, InputIterator2> mismatch (
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

View File

@ -622,6 +622,8 @@ namespace boost {
{
#if BOOST_WORKAROUND( __MWERKS__, <= 0x3003 )
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
return m_Range;
#endif

View File

@ -132,7 +132,12 @@ namespace boost {
// 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
@ -230,7 +235,7 @@ namespace boost {
\post eof()==true
*/
split_iterator() { m_bEof = true; }
split_iterator() {}
//! Copy constructor
/*!
Construct a copy of the split_iterator

View File

@ -36,6 +36,47 @@ namespace boost {
// 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
/*!
@ -45,12 +86,20 @@ namespace boost {
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:
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = false };
# else
BOOST_STATIC_CONSTANT(bool, value=false);
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
typedef mpl::bool_<has_native_replace<T>::value> type;
@ -65,12 +114,20 @@ namespace boost {
template< typename T >
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:
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = false };
# else
BOOST_STATIC_CONSTANT(bool, value=false);
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
typedef mpl::bool_<has_stable_iterators<T>::value> type;
};
@ -84,12 +141,20 @@ namespace boost {
template< typename T >
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:
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = false };
# else
BOOST_STATIC_CONSTANT(bool, value=false);
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
typedef mpl::bool_<has_const_time_insert<T>::value> type;
};
@ -103,12 +168,20 @@ namespace boost {
template< typename T >
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:
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = false };
# else
BOOST_STATIC_CONSTANT(bool, value=false);
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
typedef mpl::bool_<has_const_time_erase<T>::value> type;
};

View File

@ -20,6 +20,22 @@ namespace boost {
// 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
template<typename T, typename AllocT>
@ -59,6 +75,7 @@ namespace boost {
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_const_time_erase<T>::value> type;
};
#endif
} // namespace algorithm

View File

@ -20,6 +20,25 @@ namespace boost {
// 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
template<typename T, typename TraitsT, typename AllocT>
@ -72,6 +91,7 @@ namespace boost {
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<value> type;
};
#endif
} // namespace algorithm

View File

@ -21,6 +21,21 @@ namespace boost {
// 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
template<typename T, typename AllocT>
@ -60,6 +75,7 @@ namespace boost {
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_const_time_erase<T>::value> type;
};
#endif
} // namespace algorithm

View File

@ -20,6 +20,13 @@ namespace boost {
// 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
template<typename T, typename TraitsT, typename AllocT>
@ -36,6 +43,7 @@ namespace boost {
};
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
} // namespace algorithm
} // 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

@ -181,21 +181,6 @@ void find_test()
( (cv_result.begin()-str1.begin()) == 3) &&
( (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 );
BOOST_CHECK(
( (nc_result.begin()-str1.begin()) == 3) &&
@ -266,6 +251,19 @@ void find_test()
osstr << find_first( str1, "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

View File

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

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

@ -58,6 +58,9 @@ alias unit_test_framework
[ run hex_test4.cpp unit_test_framework : : : : hex_test4 ]
[ compile-fail hex_fail1.cpp ]
# Wrapper tests
[ run wrapper_test1.cpp unit_test_framework : : : : wrapper_test1 ]
# Gather tests
[ run gather_test1.cpp unit_test_framework : : : : gather_test1 ]
[ 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/algorithm/cxx11/is_permutation.hpp>
#include <boost/algorithm/cxx14/is_permutation.hpp>
#define BOOST_TEST_MAIN
#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
#define ITERATOR_TEST_H
/*
A set of iterator adapters for constructing test cases
From an iterator (or a pointer), you can make any class of iterator.
Assuming you want to degrade the capabilities.
Modeled closely on work that Howard Hinnant did for libc++.
A set of iterator adapters for constructing test cases
From an iterator (or a pointer), you can make any class of iterator.
Assuming you want to degrade the capabilities.
Modeled closely on work that Howard Hinnant did for libc++.
*/
#include <iterator>
@ -278,10 +269,10 @@ public:
private:
It it_;
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 ==
template <typename Iter>
@ -299,7 +290,7 @@ inline Iter base(bidirectional_iterator<Iter> i) { return i.base(); }
template <typename Iter>
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; }
#endif // ITERATORS_H

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 ();
}