From b9d89c559b2e6ad8abbab3dddf1364d08218579b Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Mon, 20 May 2013 15:37:50 +0000 Subject: [PATCH 01/17] Better 'is_permutation' implementation, tests [SVN r84389] --- .../boost/algorithm/cxx11/is_permutation.hpp | 159 +++++++++++-- .../boost/algorithm/cxx14/is_permutation.hpp | 130 ----------- test/equal_test.cpp | 159 ++++++------- test/is_permutation_test1.cpp | 87 ++++++- test/mismatch_test.cpp | 220 +++++++++--------- 5 files changed, 414 insertions(+), 341 deletions(-) delete mode 100644 include/boost/algorithm/cxx14/is_permutation.hpp diff --git a/include/boost/algorithm/cxx11/is_permutation.hpp b/include/boost/algorithm/cxx11/is_permutation.hpp index b30166c..3eff5ce 100644 --- a/include/boost/algorithm/cxx11/is_permutation.hpp +++ b/include/boost/algorithm/cxx11/is_permutation.hpp @@ -24,10 +24,6 @@ namespace boost { namespace algorithm { -#if __cplusplus >= 201103L -// Use the C++11 versions of is_permutation if it is available -using std::is_permutation; // Section 25.2.12 -#else /// \cond DOXYGEN_HIDE namespace detail { template @@ -37,18 +33,82 @@ namespace detail { template bool operator () ( const T1 &t1 ) const { return p_ ( *it_, t1 ); } private: - Predicate &p_; + Predicate p_; Iterator it_; }; + +// Preconditions: +// 1. The sequences are the same length +// 2. Any common elements on the front have been removed (not necessary for correctness, just for performance) + template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate > + bool is_permutation_inner ( ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate p ) { + // for each unique value in the sequence [first1,last1), count how many times + // it occurs, and make sure it occurs the same number of times in [first2, last2) + for ( ForwardIterator1 iter = first1; iter != last1; ++iter ) { + value_predicate pred ( p, iter ); + + /* For each value we haven't seen yet... */ + if ( std::find_if ( first1, iter, pred ) == iter ) { + std::size_t dest_count = std::count_if ( first2, last2, pred ); + if ( dest_count == 0 || dest_count != (std::size_t) std::count_if ( iter, last1, pred )) + return false; + } + } + + return true; + } + + template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> + bool is_permutation_tag ( ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate p, + std::forward_iterator_tag, std::forward_iterator_tag ) { + + // Skip the common prefix (if any) + while ( first1 != last1 && first2 != last2 && p ( *first1, *first2 )) { + ++first1; + ++first2; + } + if ( first1 != last1 && first2 != last2 ) + return boost::algorithm::detail::is_permutation_inner ( first1, last1, first2, last2, + std::equal_to::value_type> ()); + return first1 == last1 && first2 == last2; + } + + template + bool is_permutation_tag ( RandomAccessIterator1 first1, RandomAccessIterator1 last1, + RandomAccessIterator2 first2, RandomAccessIterator2 last2, + BinaryPredicate p, + std::random_access_iterator_tag, std::random_access_iterator_tag ) { + // Cheap check + if ( std::distance ( first1, last1 ) != std::distance ( first2, last2 )) + return false; + // Skip the common prefix (if any) + while ( first1 != last1 && first2 != last2 && p ( *first1, *first2 )) { + ++first1; + ++first2; + } + + if ( first1 != last1 && first2 != last2 ) + return is_permutation_inner (first1, last1, first2, last2, p); + return first1 == last1 && first2 == last2; + } + } /// \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 ) /// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2 /// -/// \param first The start of the input sequence -/// \param last One past the end of the input sequence +/// \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 p The predicate to compare elements with /// @@ -67,19 +127,7 @@ bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, // Create last2 ForwardIterator2 last2 = first2; std::advance ( last2, std::distance (first1, last1)); - - // for each unique value in the sequence [first1,last1), count how many times - // it occurs, and make sure it occurs the same number of times in [first2, last2) - for ( ForwardIterator1 iter = first1; iter != last1; ++iter ) { - detail::value_predicate pred ( p, iter ); - - /* For each value we haven't seen yet... */ - if ( std::find_if ( first1, iter, pred ) == iter ) { - std::size_t dest_count = std::count_if ( first2, last2, pred ); - if ( dest_count == 0 || dest_count != (std::size_t) std::count_if ( iter, last1, pred )) - return false; - } - } + return boost::algorithm::detail::is_permutation_inner ( first1, last1, first2, last2, p ); } return true; @@ -88,23 +136,84 @@ bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, /// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2 ) /// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2 /// -/// \param first The start of the input sequence -/// \param last One past the end of the input sequence +/// \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 /// \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 first, ForwardIterator1 last, ForwardIterator2 first2 ) +bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2 ) { // 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::is_permutation ( first, last, first2, - std::equal_to::value_type> ()); +// Skip the common prefix (if any) + std::pair eq = std::mismatch (first1, last1, first2 ); + first1 = eq.first; + first2 = eq.second; + if ( first1 != last1 ) { + // Create last2 + ForwardIterator2 last2 = first2; + std::advance ( last2, std::distance (first1, last1)); + return boost::algorithm::detail::is_permutation_inner ( first1, last1, first2, last2, + std::equal_to::value_type> ()); + } + 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::value_type> (), + typename std::iterator_traits::iterator_category (), + typename std::iterator_traits::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::iterator_category (), + typename std::iterator_traits::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 /// diff --git a/include/boost/algorithm/cxx14/is_permutation.hpp b/include/boost/algorithm/cxx14/is_permutation.hpp deleted file mode 100644 index 779acef..0000000 --- a/include/boost/algorithm/cxx14/is_permutation.hpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - 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) -*/ - -/// \file equal.hpp -/// \brief Determines if one -/// \author Marshall Clow - -#ifndef BOOST_ALGORITHM_IS_PERMUTATION_HPP -#define BOOST_ALGORITHM_IS_PERMUTATION_HPP - -#include -#include // for std::equal_to - -namespace boost { namespace algorithm { - -namespace detail { - - template - struct is_perm_eq : public std::binary_function { - bool operator () ( const T1& v1, const T2& v2 ) const { return v1 == v2 ;} - }; - - - template - bool is_permutation ( 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::is_permutation ( first1, last1, first2, pred ); - } - - - template - bool is_permutation ( - ForwardIterator1 first1, ForwardIterator1 last1, - ForwardIterator2 first2, ForwardIterator2 last2, - BinaryPredicate pred, - std::forward_iterator_tag, std::forward_iterator_tag ) - { - - // Look for common prefix - for (; first1 != last1 && first2 != last2; ++first1, ++first2) - if (!pred(*first1, *first2)) - goto not_done; - // We've reached the end of one of the sequences without a mismatch. - return first1 == last1 && first2 == last2; - not_done: - - // Check and make sure that we have the same # of elements left - typedef typename std::iterator_traits::difference_type diff1_t; - diff1_t len1 = _VSTD::distance(first1, last1); - typedef typename std::iterator_traits::difference_type diff2_t; - diff2_t len2 = _VSTD::distance(first2, last2); - if (len1 != len2) - return false; - - // For each element in [f1, l1) see if there are the - // same number of equal elements in [f2, l2) - for ( ForwardIterator1 i = first1; i != last1; ++i ) - { - // Have we already counted this value? - ForwardIterator1 j; - for ( j = first1; j != i; ++j ) - if (pred(*j, *i)) - break; - if ( j == i ) // didn't find it... - { - // Count number of *i in [f2, l2) - diff1_t c2 = 0; - for ( ForwardIterator2 iter2 = first2; iter2 != last2; ++iter2 ) - if (pred(*i, *iter2)) - ++c2; - if (c2 == 0) - return false; - - // Count number of *i in [i, l1) - diff1_t c1 = 0; - for (_ForwardIterator1 iter1 = i; iter1 != last1; ++iter1 ) - if (pred(*i, *iter1)) - ++c1; - if (c1 != c2) - return false; - } - } - return true; - } - -} - - -template -bool is_permutation ( - ForwardIterator1 first1, ForwardIterator1 last1, - ForwardIterator2 first2, ForwardIterator2 last2, - BinaryPredicate pred ) -{ - return boost::algorithm::detail::is_permutation ( - first1, last1, first2, last2, pred, - typename std::iterator_traits::iterator_category (), - typename std::iterator_traits::iterator_category ()); -} - -template -bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, - ForwardIterator2 first2, ForwardIterator2 last2 ) -{ - typedef typename iterator_traits<_ForwardIterator1>::value_type value1_t; - typedef typename iterator_traits<_ForwardIterator2>::value_type value2_t; - return boost::algorithm::detail::is_permutation ( - first1, last1, first2, last2, - boost::algorithm::detail::is_perm_eq< - typename std::iterator_traits::value_type, - typename std::iterator_traits::value_type> (), - typename std::iterator_traits::iterator_category (), - typename std::iterator_traits::iterator_category ()); -} - -// There are already range-based versions of these. - -}} // namespace boost and algorithm - -#endif // BOOST_ALGORITHM_IS_PERMUTATION_HPP diff --git a/test/equal_test.cpp b/test/equal_test.cpp index a1bda1a..c54e64d 100644 --- a/test/equal_test.cpp +++ b/test/equal_test.cpp @@ -24,9 +24,9 @@ bool never_eq ( const T&, const T& ) { return false; } int comparison_count = 0; template bool counting_equals ( const T &a, const T &b ) { - ++comparison_count; - return a == b; - } + ++comparison_count; + return a == b; + } namespace ba = boost::algorithm; @@ -37,86 +37,89 @@ void test_equal () const int sz = sizeof (num)/sizeof(num[0]); -// Empty sequences are equal to each other, but not to non-empty sequences - BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num), - input_iterator(num), input_iterator(num))); - BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num), - input_iterator(num), input_iterator(num), - never_eq )); - BOOST_CHECK ( ba::equal ( random_access_iterator(num), random_access_iterator(num), - random_access_iterator(num), random_access_iterator(num), - never_eq )); - - BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num), - input_iterator(num), input_iterator(num + 1))); - BOOST_CHECK (!ba::equal ( input_iterator(num + 1), input_iterator(num + 2), - input_iterator(num), input_iterator(num))); - BOOST_CHECK (!ba::equal ( random_access_iterator(num + 1), random_access_iterator(num + 2), - random_access_iterator(num), random_access_iterator(num))); +// Empty sequences are equal to each other, but not to non-empty sequences + BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num), + input_iterator(num), input_iterator(num))); + BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num), + input_iterator(num), input_iterator(num), + never_eq )); + BOOST_CHECK ( ba::equal ( random_access_iterator(num), random_access_iterator(num), + random_access_iterator(num), random_access_iterator(num), + never_eq )); + + BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num), + input_iterator(num), input_iterator(num + 1))); + BOOST_CHECK (!ba::equal ( input_iterator(num + 1), input_iterator(num + 2), + input_iterator(num), input_iterator(num))); + BOOST_CHECK (!ba::equal ( random_access_iterator(num + 1), random_access_iterator(num + 2), + random_access_iterator(num), random_access_iterator(num))); -// Single element sequences are equal if they contain the same value - BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + 1), - input_iterator(num), input_iterator(num + 1))); - BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + 1), - input_iterator(num), input_iterator(num + 1), - eq )); - BOOST_CHECK ( ba::equal ( random_access_iterator(num), random_access_iterator(num + 1), - random_access_iterator(num), random_access_iterator(num + 1), - eq )); - BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + 1), - input_iterator(num), input_iterator(num + 1), - never_eq )); - BOOST_CHECK (!ba::equal ( random_access_iterator(num), random_access_iterator(num + 1), - random_access_iterator(num), random_access_iterator(num + 1), - never_eq )); +// Single element sequences are equal if they contain the same value + BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + 1), + input_iterator(num), input_iterator(num + 1))); + BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + 1), + input_iterator(num), input_iterator(num + 1), + eq )); + BOOST_CHECK ( ba::equal ( random_access_iterator(num), random_access_iterator(num + 1), + random_access_iterator(num), random_access_iterator(num + 1), + eq )); + BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + 1), + input_iterator(num), input_iterator(num + 1), + never_eq )); + BOOST_CHECK (!ba::equal ( random_access_iterator(num), random_access_iterator(num + 1), + random_access_iterator(num), random_access_iterator(num + 1), + never_eq )); - BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + 1), - input_iterator(num + 1), input_iterator(num + 2))); - BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + 1), - input_iterator(num + 1), input_iterator(num + 2), - eq )); + BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + 1), + input_iterator(num + 1), input_iterator(num + 2))); + BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + 1), + input_iterator(num + 1), input_iterator(num + 2), + eq )); - BOOST_CHECK (!ba::equal ( input_iterator(num + 2), input_iterator(num + 3), - input_iterator(num), input_iterator(num + 1))); - BOOST_CHECK (!ba::equal ( input_iterator(num + 2), input_iterator(num + 3), - input_iterator(num), input_iterator(num + 1), - eq )); - -// Identical long sequences are equal. - BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz))); - BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz), - eq )); - BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz), - never_eq )); + BOOST_CHECK (!ba::equal ( input_iterator(num + 2), input_iterator(num + 3), + input_iterator(num), input_iterator(num + 1))); + BOOST_CHECK (!ba::equal ( input_iterator(num + 2), input_iterator(num + 3), + input_iterator(num), input_iterator(num + 1), + eq )); + +// Identical long sequences are equal. + BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz))); + BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz), + eq )); + BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz), + never_eq )); + BOOST_CHECK ( ba::equal ( input_iterator(num), input_iterator(num + sz), + random_access_iterator(num), random_access_iterator(num + sz), + eq )); -// different sequences are different - BOOST_CHECK (!ba::equal ( input_iterator(num + 1), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz))); - BOOST_CHECK (!ba::equal ( input_iterator(num + 1), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz), - eq )); - BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz - 1))); - BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz - 1), - eq )); +// different sequences are different + BOOST_CHECK (!ba::equal ( input_iterator(num + 1), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz))); + BOOST_CHECK (!ba::equal ( input_iterator(num + 1), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz), + eq )); + BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz - 1))); + BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz - 1), + eq )); -// When there's a cheap check, bail early - comparison_count = 0; - BOOST_CHECK (!ba::equal ( random_access_iterator(num), random_access_iterator(num + sz), - random_access_iterator(num), random_access_iterator(num + sz - 1), - counting_equals )); - BOOST_CHECK ( comparison_count == 0 ); -// And when there's not, we can't - comparison_count = 0; - BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz - 1), - counting_equals )); - BOOST_CHECK ( comparison_count > 0 ); - +// When there's a cheap check, bail early + comparison_count = 0; + BOOST_CHECK (!ba::equal ( random_access_iterator(num), random_access_iterator(num + sz), + random_access_iterator(num), random_access_iterator(num + sz - 1), + counting_equals )); + BOOST_CHECK ( comparison_count == 0 ); +// And when there's not, we can't + comparison_count = 0; + BOOST_CHECK (!ba::equal ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz - 1), + counting_equals )); + BOOST_CHECK ( comparison_count > 0 ); + } diff --git a/test/is_permutation_test1.cpp b/test/is_permutation_test1.cpp index 2ccd06a..e819643 100644 --- a/test/is_permutation_test1.cpp +++ b/test/is_permutation_test1.cpp @@ -19,10 +19,95 @@ #include #include +#include "iterator_test.hpp" + +template +bool eq ( const T& a, const T& b ) { return a == b; } + +template +bool never_eq ( const T&, const T& ) { return false; } + namespace ba = boost::algorithm; -// namespace ba = boost; void test_sequence1 () { + int num[] = { 1, 1, 2, 3, 5 }; + const int sz = sizeof (num)/sizeof(num[0]); + +// Empty sequences + BOOST_CHECK ( + ba::is_permutation ( + forward_iterator(num), forward_iterator(num), + forward_iterator(num))); + BOOST_CHECK ( + ba::is_permutation ( + forward_iterator(num), forward_iterator(num), + forward_iterator(num), forward_iterator(num))); + BOOST_CHECK ( + ba::is_permutation ( + random_access_iterator(num), random_access_iterator(num), + random_access_iterator(num), random_access_iterator(num))); + BOOST_CHECK ( + ba::is_permutation ( + forward_iterator(num), forward_iterator(num), + forward_iterator(num), + never_eq )); // Since the sequences are empty, the pred is never called + +// Empty vs. non-empty + BOOST_CHECK ( ! + ba::is_permutation ( + forward_iterator(num), forward_iterator(num), + forward_iterator(num), forward_iterator(num + 1))); + + BOOST_CHECK ( ! + ba::is_permutation ( + forward_iterator(num + 1), forward_iterator(num + 2), + forward_iterator(num), forward_iterator(num))); + + BOOST_CHECK ( ! + ba::is_permutation ( + random_access_iterator(num + 1), random_access_iterator(num + 2), + random_access_iterator(num), random_access_iterator(num))); + + BOOST_CHECK ( ! + ba::is_permutation ( + random_access_iterator(num), random_access_iterator(num), + random_access_iterator(num + 1), random_access_iterator(num + 2))); + +// Something should be a permutation of itself + BOOST_CHECK ( + ba::is_permutation ( + forward_iterator(num), forward_iterator(num + sz), + forward_iterator(num))); + BOOST_CHECK ( + ba::is_permutation ( + forward_iterator(num), forward_iterator(num + sz), + forward_iterator(num), eq )); + BOOST_CHECK ( + ba::is_permutation ( + forward_iterator(num), forward_iterator(num + sz), + forward_iterator(num), forward_iterator(num + sz ))); + BOOST_CHECK ( + ba::is_permutation ( + forward_iterator(num), forward_iterator(num + sz), + forward_iterator(num), forward_iterator(num + sz ), + eq )); + + BOOST_CHECK ( + ba::is_permutation ( + random_access_iterator(num), random_access_iterator(num + sz), + random_access_iterator(num), random_access_iterator(num + sz))); + BOOST_CHECK ( + ba::is_permutation ( + random_access_iterator(num), random_access_iterator(num + sz), + random_access_iterator(num), random_access_iterator(num + sz), + eq )); + BOOST_CHECK ( + ba::is_permutation ( + random_access_iterator(num), random_access_iterator(num + sz), + forward_iterator(num), forward_iterator(num + sz), + eq )); + + std::vector v, v1; v.clear (); diff --git a/test/mismatch_test.cpp b/test/mismatch_test.cpp index 19e0477..61a7506 100644 --- a/test/mismatch_test.cpp +++ b/test/mismatch_test.cpp @@ -24,9 +24,9 @@ bool never_eq ( const T&, const T& ) { return false; } namespace ba = boost::algorithm; template -bool iter_eq ( std::pair pr, Iter1 first, Iter2 second ) { - return pr.first == first && pr.second == second; - } +bool iter_eq ( std::pair pr, Iter1 first, Iter2 second ) { + return pr.first == first && pr.second == second; + } void test_mismatch () { @@ -35,123 +35,129 @@ void test_mismatch () const int sz = sizeof (num)/sizeof(num[0]); -// No mismatch for empty sequences - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num), - input_iterator(num), input_iterator(num)), - input_iterator(num), input_iterator(num))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num), - input_iterator(num), input_iterator(num), - never_eq ), - input_iterator(num), input_iterator(num))); +// No mismatch for empty sequences + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num), + input_iterator(num), input_iterator(num)), + input_iterator(num), input_iterator(num))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num), + input_iterator(num), input_iterator(num), + never_eq ), + input_iterator(num), input_iterator(num))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( random_access_iterator(num), random_access_iterator(num), - random_access_iterator(num), random_access_iterator(num), - never_eq ), - random_access_iterator(num), random_access_iterator(num))); - -// Empty vs. non-empty mismatch immediately - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num), - input_iterator(num), input_iterator(num + 1)), - input_iterator(num), input_iterator(num))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( random_access_iterator(num), random_access_iterator(num), + random_access_iterator(num), random_access_iterator(num), + never_eq ), + random_access_iterator(num), random_access_iterator(num))); + +// Empty vs. non-empty mismatch immediately + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num), + input_iterator(num), input_iterator(num + 1)), + input_iterator(num), input_iterator(num))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num + 1), input_iterator(num + 2), - input_iterator(num), input_iterator(num)), - input_iterator(num + 1), input_iterator(num))); - - BOOST_CHECK ( iter_eq ( - ba::mismatch ( random_access_iterator(num + 1), random_access_iterator(num + 2), - random_access_iterator(num), random_access_iterator(num)), - random_access_iterator(num + 1), random_access_iterator(num))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num + 1), input_iterator(num + 2), + input_iterator(num), input_iterator(num)), + input_iterator(num + 1), input_iterator(num))); + + BOOST_CHECK ( iter_eq ( + ba::mismatch ( random_access_iterator(num + 1), random_access_iterator(num + 2), + random_access_iterator(num), random_access_iterator(num)), + random_access_iterator(num + 1), random_access_iterator(num))); -// Single element sequences are equal if they contain the same value - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num + 1), - input_iterator(num), input_iterator(num + 1)), - input_iterator(num + 1), input_iterator(num + 1))); - - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num + 1), +// Single element sequences are equal if they contain the same value + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num + 1), + input_iterator(num), input_iterator(num + 1)), + input_iterator(num + 1), input_iterator(num + 1))); + + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num + 1), input_iterator(num), input_iterator(num + 1), - eq ), - input_iterator(num + 1), input_iterator(num + 1))); - - BOOST_CHECK ( iter_eq ( - ba::mismatch ( random_access_iterator(num), random_access_iterator(num + 1), - random_access_iterator(num), random_access_iterator(num + 1), - eq ), - random_access_iterator(num + 1), random_access_iterator(num + 1))); + eq ), + input_iterator(num + 1), input_iterator(num + 1))); + + BOOST_CHECK ( iter_eq ( + ba::mismatch ( random_access_iterator(num), random_access_iterator(num + 1), + random_access_iterator(num), random_access_iterator(num + 1), + eq ), + random_access_iterator(num + 1), random_access_iterator(num + 1))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num + 1), - input_iterator(num), input_iterator(num + 1), - never_eq ), - input_iterator(num), input_iterator(num))); - - BOOST_CHECK ( iter_eq ( - ba::mismatch ( random_access_iterator(num), random_access_iterator(num + 1), - random_access_iterator(num), random_access_iterator(num + 1), - never_eq ), - random_access_iterator(num), random_access_iterator(num))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num + 1), + input_iterator(num), input_iterator(num + 1), + never_eq ), + input_iterator(num), input_iterator(num))); + + BOOST_CHECK ( iter_eq ( + ba::mismatch ( random_access_iterator(num), random_access_iterator(num + 1), + random_access_iterator(num), random_access_iterator(num + 1), + never_eq ), + random_access_iterator(num), random_access_iterator(num))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num + 1), - input_iterator(num + 1), input_iterator(num + 2)), - input_iterator(num + 1), input_iterator(num + 2))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num + 1), + input_iterator(num + 1), input_iterator(num + 2)), + input_iterator(num + 1), input_iterator(num + 2))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num + 1), - input_iterator(num + 1), input_iterator(num + 2), - eq ), - input_iterator(num + 1), input_iterator(num + 2))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num + 1), + input_iterator(num + 1), input_iterator(num + 2), + eq ), + input_iterator(num + 1), input_iterator(num + 2))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num + 2), input_iterator(num + 3), - input_iterator(num), input_iterator(num + 1)), - input_iterator(num + 2), input_iterator(num))); - - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num + 2), input_iterator(num + 3), - input_iterator(num), input_iterator(num + 1), - eq ), - input_iterator(num + 2), input_iterator(num))); - - - -// Identical long sequences are equal. - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz)), - input_iterator(num + sz), input_iterator(num + sz))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num + 2), input_iterator(num + 3), + input_iterator(num), input_iterator(num + 1)), + input_iterator(num + 2), input_iterator(num))); + + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num + 2), input_iterator(num + 3), + input_iterator(num), input_iterator(num + 1), + eq ), + input_iterator(num + 2), input_iterator(num))); + + + +// Identical long sequences are equal. + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz)), + input_iterator(num + sz), input_iterator(num + sz))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz), - eq ), - input_iterator(num + sz), input_iterator(num + sz))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz), + eq ), + input_iterator(num + sz), input_iterator(num + sz))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz), - never_eq ), - input_iterator(num), input_iterator(num))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz), + never_eq ), + input_iterator(num), input_iterator(num))); -// different sequences are different - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num + 1), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz)), - input_iterator(num + 2), input_iterator(num + 1))); + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num), input_iterator(num + sz), + random_access_iterator(num), random_access_iterator(num + sz), + never_eq ), + input_iterator(num), random_access_iterator(num))); - BOOST_CHECK ( iter_eq ( - ba::mismatch ( input_iterator(num + 1), input_iterator(num + sz), - input_iterator(num), input_iterator(num + sz), - eq ), - input_iterator(num + 2), input_iterator(num + 1))); +// different sequences are different + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num + 1), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz)), + input_iterator(num + 2), input_iterator(num + 1))); + + BOOST_CHECK ( iter_eq ( + ba::mismatch ( input_iterator(num + 1), input_iterator(num + sz), + input_iterator(num), input_iterator(num + sz), + eq ), + input_iterator(num + 2), input_iterator(num + 1))); } From 73cfe03b97811ad4bf0aecc29b986ab90a39a344 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Thu, 23 May 2013 18:28:23 +0000 Subject: [PATCH 02/17] Added docs for C++14 variants of 'equal' and 'mismatch' [SVN r84447] --- doc/Jamfile.v2 | 6 +++- doc/algorithm.qbk | 5 +++ doc/equal.qbk | 80 +++++++++++++++++++++++++++++++++++++++++++++ doc/mismatch.qbk | 82 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 doc/equal.qbk create mode 100644 doc/mismatch.qbk diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 515b9a5..6af1129 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -18,7 +18,11 @@ using boostbook ; doxygen autodoc : - [ glob ../../../boost/algorithm/*.hpp ../../../boost/algorithm/searching/*.hpp ] + [ glob ../../../boost/algorithm/*.hpp + ../../../boost/algorithm/searching/*.hpp + ../../../boost/algorithm/cxx11/*.hpp + ../../../boost/algorithm/cxx14/*.hpp + ] : "PREDEFINED=\"BOOST_ALGORITHM_DOXYGEN=1\"" WARNINGS=YES # Default NO, but useful to see warnings, especially in a logfile. diff --git a/doc/algorithm.qbk b/doc/algorithm.qbk index 10098c0..23d615e 100644 --- a/doc/algorithm.qbk +++ b/doc/algorithm.qbk @@ -56,6 +56,11 @@ Thanks to all the people who have reviewed this library and made suggestions for [include partition_point.qbk] [endsect] +[section:CXX14 C++14 Algorithms] +[include equal.qbk] +[include mismatch.qbk] +[endsect] + [section:Misc Other Algorithms] [include clamp-hpp.qbk] [include gather.qbk] diff --git a/doc/equal.qbk b/doc/equal.qbk new file mode 100644 index 0000000..859a8a1 --- /dev/null +++ b/doc/equal.qbk @@ -0,0 +1,80 @@ +[/ File equal.qbk] + +[section:equal equal ] + +[/license +Copyright (c) 2013 Marshall Clow + +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) +] + +The header file 'equal.hpp' contains two variants of a the stl algorithm `equal`. The algorithm tests to see if two sequences contain equal values; + +Before (the proposed) C++14 the algorithm `std::equal` took three iterators and an optional comparison predicate. The first two iterators `[first1, last1)` defined a sequence, and the second one `first2` defined the start of the second sequence. The second sequence was assumed to be the same length as the first. + +In C++14, two new variants were introduced, taking four iterators and an optional comparison predicate. The four iterators define two sequences `[first1, last1)` and `[first2, last2)` explicitly, rather than defining the second one implicitly. This leads to correct answers in more cases (and avoid undefined behavior in others). + +Consider the two sequences: +``` + auto seq1 = { 0, 1, 2 }; + auto seq2 = { 0, 1, 2, 3, 4 }; + + 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 (), 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). + +However, if the two sequences are specified completely, it's clear that they are not equal. + +[heading interface] + +The function `equal` returns true if the two sequences compare equal; i.e, if each element in the sequence compares equal to the corresponding element in the other sequence. One version uses `std::equal_to` to do the comparison; the other lets the caller pass predicate to do the comparisons. + +`` +template +bool equal ( InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2 ); + +template +bool equal ( InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred ); +`` + +[heading Examples] + +Given the container `c1` containing `{ 0, 1, 2, 3, 14, 15 }`, and `c2` containing `{ 1, 2, 3 }`, then +`` +equal ( c1.begin (), c1.end (), c2.begin (), c2.end ()) --> false +equal ( c1.begin () + 1, c1.begin () + 3, c2.begin (), c2.end ()) --> true +equal ( c1.end (), c1.end (), c2.end (), c2.end ()) --> true // empty sequences are alway equal to each other +`` + +[heading Iterator Requirements] + +`equal` works on all iterators except output iterators. + +[heading Complexity] + +Both of the variants of `equal` 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. + +[heading Exception Safety] + +Both of the variants of `equal` take their parameters by value and do not depend upon any global state. Therefore, all the routines in this file provide the strong exception guarantee. + +[heading Notes] + +* The four iterator version of the routine `equal` is part of the C++14 standard. When C++14 standard library implementations become available, the implementation from the standard library should be used. + +* `equal` returns true for two empty ranges, no matter what predicate is passed to test against. + +[endsect] + +[/ File equal.qbk +Copyright 2011 Marshall Clow +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). +] + diff --git a/doc/mismatch.qbk b/doc/mismatch.qbk new file mode 100644 index 0000000..630bdc1 --- /dev/null +++ b/doc/mismatch.qbk @@ -0,0 +1,82 @@ +[/ File mismatch.qbk] + +[section:mismatch mismatch ] + +[/license +Copyright (c) 2013 Marshall Clow + +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) +] + +The header file 'mismatch.hpp' contains two variants of a the stl algorithm `mismatch`. The algorithm finds the first point in two sequences where they do not match. + +Before (the proposed) C++14 the algorithm `std::mismatch` took three iterators and an optional comparison predicate. The first two iterators `[first1, last1)` defined a sequence, and the second one `first2` defined the start of the second sequence. The second sequence was assumed to be the same length as the first. + +In C++14, two new variants were introduced, taking four iterators and an optional comparison predicate. The four iterators define two sequences `[first1, last1)` and `[first2, last2)` explicitly, rather than defining the second one implicitly. This leads to correct answers in more cases (and avoid undefined behavior in others). + +Consider the two sequences: +``` + auto seq1 = { 0, 1, 2 }; + auto seq2 = { 0, 1, 2, 3, 4 }; + + 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 (), 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). + +However, if the two sequences are specified completely, it's clear that where the mismatch occurs. + +[heading interface] + +The function `mismatch` returns a pair of iterators which denote the first mismatching elements in each sequence. If the sequences match completely, `mismatch` returns their end iterators. One version uses `std::equal_to` to do the comparison; the other lets the caller pass predicate to do the comparisons. + +`` +template +std::pair +mismatch ( InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2 ); + +template +std::pair +mismatch ( InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred ); +`` + +[heading Examples] + +Given the container `c1` containing `{ 0, 1, 2, 3, 14, 15 }`, and `c2` containing `{ 1, 2, 3 }`, then +`` +mismatch ( c1.begin(), c1.end(), c2.begin(), c2.end()) --> // first elements do not match +mismatch ( c1.begin() + 1, c1.begin() + 4, c2.begin(), c2.end()) --> // all elements of `c2` match +mismatch ( c1.end(), c1.end(), c2.end(), c2.end()) --> // empty sequences don't match at the end. +`` + +[heading Iterator Requirements] + +`mismatch` works on all iterators except output iterators. + +[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 equal at any point, the routine will terminate immediately, without examining the rest of the elements. + +[heading Exception Safety] + +Both of the variants of `mismatch` take their parameters by value and do not depend upon any global state. Therefore, all the routines in this file provide the strong exception guarantee. + +[heading Notes] + +* If the sequences are equal (or both are empty), then mismatch returns the end iterators of both sequences. + +* The four iterator version of the routine `mismatch` is part of the C++14 standard. When C++14 standard library implementations become available, the implementation from the standard library should be used. + +[endsect] + +[/ File mismatch.qbk +Copyright 2011 Marshall Clow +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). +] + From 3e5f571230011469c577506058aa1c99a8d9d0c6 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Thu, 23 May 2013 18:29:49 +0000 Subject: [PATCH 03/17] fixed Doxygen comment [SVN r84448] --- include/boost/algorithm/cxx14/mismatch.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/boost/algorithm/cxx14/mismatch.hpp b/include/boost/algorithm/cxx14/mismatch.hpp index 5229e3b..c45fded 100644 --- a/include/boost/algorithm/cxx14/mismatch.hpp +++ b/include/boost/algorithm/cxx14/mismatch.hpp @@ -17,8 +17,6 @@ namespace boost { namespace algorithm { -template - /// \fn mismatch ( InputIterator1 first1, InputIterator1 last1, /// InputIterator2 first2, InputIterator2 last2, /// BinaryPredicate pred ) @@ -29,6 +27,7 @@ template /// \param first2 The start of the second range. /// \param last2 One past the end of the second range. /// \param pred A predicate for comparing the elements of the ranges +template std::pair mismatch ( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, From 44d65cb4ae4026f70a520e371583f66a0c653f07 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Tue, 28 May 2013 19:36:04 +0000 Subject: [PATCH 04/17] Added documentation for 'is_permutation' [SVN r84538] --- doc/algorithm.qbk | 1 + doc/is_partitioned.qbk | 2 +- doc/is_permutation.qbk | 87 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 doc/is_permutation.qbk diff --git a/doc/algorithm.qbk b/doc/algorithm.qbk index 23d615e..66971d1 100644 --- a/doc/algorithm.qbk +++ b/doc/algorithm.qbk @@ -53,6 +53,7 @@ Thanks to all the people who have reviewed this library and made suggestions for [include one_of.qbk] [include ordered-hpp.qbk] [include is_partitioned.qbk] +[include is_permutation.qbk] [include partition_point.qbk] [endsect] diff --git a/doc/is_partitioned.qbk b/doc/is_partitioned.qbk index 3c7075b..16dce6a 100644 --- a/doc/is_partitioned.qbk +++ b/doc/is_partitioned.qbk @@ -18,7 +18,7 @@ The routine `is_partitioned` takes a sequence and a predicate. It returns true i [heading interface] -The function `is_partitioned` returns true the items in the sequence are separated according to their ability to satisfy the predicate. There are two versions; one takes two iterators, and the other takes a range. +The function `is_partitioned` returns true if the items in the sequence are separated according to their ability to satisfy the predicate. There are two versions; one takes two iterators, and the other takes a range. `` template diff --git a/doc/is_permutation.qbk b/doc/is_permutation.qbk new file mode 100644 index 0000000..47d692c --- /dev/null +++ b/doc/is_permutation.qbk @@ -0,0 +1,87 @@ +[/ File is_permutation.qbk] + +[section:is_permutation is_permutation ] + +[/license +Copyright (c) 2010-2012 Marshall Clow + +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) +] + +The header file 'is_permutation.hpp' contains six variants of a single algorithm, `is_permutation`. The algorithm tests to see if one sequence is a permutation of a second one; in other words, it contains all the same members, possibly in a different order. + +The routine `is_permutation` takes two sequences and an (optional) predicate. It returns true if the two sequences contain the same members. If it is passed a predicate, it uses the predicate to compare the elements of the sequence to see if they are the same. + +`is_permutation` come in three forms. The first one takes two iterators to define the first range, and the starting iterator of the second range. The second form takes a two iterators to define the first range and two more to define the second range. The third form takes a single range parameter, and uses Boost.Range to traverse it. + + +[heading Interface] + +The function `is_permutation` returns true if the two input sequences contain the same elements. There are six versions; two take three iterators, two take four iterators, and the other two take two ranges. + +In general, you should prefer the four iterator versions over the three iterator ones. The three iterator version has to "create" the fourth iterator internally by calling `std::advance(first2, std::distance(first1,last1))`, and if the second sequence is shorter than the first, that's undefined behavior. + +`` +template< class ForwardIterator1, class ForwardIterator2 > +bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2 ); + +template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate > +bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, BinaryPredicate p ); + + +template< class ForwardIterator1, class ForwardIterator2 > +bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2 ); + +template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate > +bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate p ); + +template +bool is_permutation ( const Range &r, ForwardIterator first2 ); + +template +bool is_permutation ( const Range &r, ForwardIterator first2, BinaryPredicate pred ); + +`` + +[heading Examples] + +Given the container `c1` containing `{ 0, 1, 2, 3, 14, 15 }`, and `c2` containing `{ 15, 14, 3, 1, 2 }`, then +`` +is_permutation ( c1.begin(), c1.end (), c2.begin(), c2.end ()) --> false +is_permutation ( c1.begin() + 1, c1.end (), c2.begin(), c2.end ()) --> true + +is_permutation ( c1.end (), c1.end (), c2.end(), c2.end ()) --> true // all empty ranges are permutations of each other +`` + +[heading Iterator Requirements] + +`is_permutation` works on forward iterators or better. + +[heading Complexity] + +All of the variants of `is_permutation` run in ['O(N^2)] (quadratic) time; that is, they compare against each element in the list (potentially) N times. If passed random-access iterators, `is_permutation` can return quickly if the sequences are different sizes. + +[heading Exception Safety] + +All of the variants of `is_permutation` take their parameters by value, and do not depend upon any global state. Therefore, all the routines in this file provide the strong exception guarantee. + +[heading Notes] + +* The three iterator versions of the routine `is_permutation` is part of the C++11 standard. When compiled using a C++11 implementation, the implementation from the standard library will be used. + +* The four iterator versions of the routine `is_permutation` is part of the proposed C++14 standard. When C++14 standard libraries become available, the implementation should be changed to use the implementation from the standard library (if available). + +* `is_permutation` returns true when passed a pair empty ranges, no matter what predicate is passed to test with. + +[endsect] + +[/ File is_permutation.qbk +Copyright 2011 Marshall Clow +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). +] + From 05475fec0f62740a7bf03c4c3821cb7c9f26ae3a Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Wed, 5 Jun 2013 20:24:00 +0000 Subject: [PATCH 05/17] Fixed some mixed singular/plural bits [SVN r84648] --- doc/is_permutation.qbk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/is_permutation.qbk b/doc/is_permutation.qbk index 47d692c..267bfab 100644 --- a/doc/is_permutation.qbk +++ b/doc/is_permutation.qbk @@ -71,11 +71,11 @@ All of the variants of `is_permutation` take their parameters by value, and do n [heading Notes] -* The three iterator versions of the routine `is_permutation` is part of the C++11 standard. When compiled using a C++11 implementation, the implementation from the standard library will be used. +* The three iterator versions of the routine `is_permutation` are part of the C++11 standard. When compiled using a C++11 implementation, the implementation from the standard library will be used. -* The four iterator versions of the routine `is_permutation` is part of the proposed C++14 standard. When C++14 standard libraries become available, the implementation should be changed to use the implementation from the standard library (if available). +* The four iterator versions of the routine `is_permutation` are part of the proposed C++14 standard. When C++14 standard libraries become available, the implementation should be changed to use the implementation from the standard library (if available). -* `is_permutation` returns true when passed a pair empty ranges, no matter what predicate is passed to test with. +* `is_permutation` returns true when passed a pair of empty ranges, no matter what predicate is passed to test with. [endsect] From 4f269a270c37bcf14c4bcb6a48da8cc7cbabc8d2 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Tue, 18 Jun 2013 14:46:32 +0000 Subject: [PATCH 06/17] Fix error in compile-fail test; now fails to compile for the right reason [SVN r84824] --- test/gather_fail1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/gather_fail1.cpp b/test/gather_fail1.cpp index 2670bd0..7fe5b7f 100644 --- a/test/gather_fail1.cpp +++ b/test/gather_fail1.cpp @@ -27,7 +27,7 @@ void test_sequence1 () { typedef input_iterator::iterator> II; // This should fail to compile, since gather doesn't work with input iterators - (void) ba::gather ( II( v.begin ()), II( v.end ()), II( v.begin ()), is_even ); + (void) ba::gather ( II( v.begin ()), II( v.end ()), II( v.begin ()), is_ten ); } From 5f79807d02c692ee021ca0738e72df7556fee5bd Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Mon, 22 Jul 2013 15:46:43 +0000 Subject: [PATCH 07/17] Removed unused typedef; Refs #8546 [SVN r85106] --- include/boost/algorithm/string/detail/finder.hpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/include/boost/algorithm/string/detail/finder.hpp b/include/boost/algorithm/string/detail/finder.hpp index 93310d0..40112dd 100644 --- a/include/boost/algorithm/string/detail/finder.hpp +++ b/include/boost/algorithm/string/detail/finder.hpp @@ -142,7 +142,6 @@ namespace boost { ForwardIteratorT End, std::forward_iterator_tag ) const { - typedef ForwardIteratorT input_iterator_type; typedef iterator_range result_type; first_finder_type first_finder( @@ -263,7 +262,6 @@ namespace boost { ForwardIteratorT End, unsigned int N) const { - typedef ForwardIteratorT input_iterator_type; typedef iterator_range result_type; // Sanity check @@ -298,7 +296,6 @@ namespace boost { ForwardIteratorT End, unsigned int N) const { - typedef ForwardIteratorT input_iterator_type; typedef iterator_range result_type; // Sanity check @@ -362,7 +359,6 @@ namespace boost { unsigned int N, std::random_access_iterator_tag ) { - typedef ForwardIteratorT input_iterator_type; typedef iterator_range result_type; if ( (End<=Begin) || ( static_cast(End-Begin) < N ) ) @@ -436,7 +432,6 @@ namespace boost { unsigned int N, std::random_access_iterator_tag ) { - typedef ForwardIteratorT input_iterator_type; typedef iterator_range result_type; if ( (End<=Begin) || ( static_cast(End-Begin) < N ) ) From fc0fe6af52307e766ca5c636360e20732cbcaed7 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Mon, 19 Aug 2013 17:52:56 +0000 Subject: [PATCH 08/17] Fixed typo "one_of_value" --> "one_of_equal". Refs #9010 [SVN r85397] --- doc/one_of.qbk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/one_of.qbk b/doc/one_of.qbk index 4170407..e5d873b 100644 --- a/doc/one_of.qbk +++ b/doc/one_of.qbk @@ -75,7 +75,7 @@ All of the variants of `one_of` and `one_of_equal` take their parameters by valu * `one_of` and `one_of_equal` both return false for empty ranges, no matter what is passed to test against. -* The second parameter to `one_of_value` is a template parameter, rather than deduced from the first parameter (`std::iterator_traits::value_type`) because that allows more flexibility for callers, and takes advantage of built-in comparisons for the type that is pointed to by the iterator. The function is defined to return true if, for one element in the sequence, the expression `*iter == val` evaluates to true (where `iter` is an iterator to each element in the sequence) +* The second parameter to `one_of_equal` is a template parameter, rather than deduced from the first parameter (`std::iterator_traits::value_type`) because that allows more flexibility for callers, and takes advantage of built-in comparisons for the type that is pointed to by the iterator. The function is defined to return true if, for one element in the sequence, the expression `*iter == val` evaluates to true (where `iter` is an iterator to each element in the sequence) [endsect] From fe51eb60a922726463e4fdad091f1682d544ad03 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Sun, 25 Aug 2013 16:29:01 +0000 Subject: [PATCH 09/17] Rewrote iota_n to use pre-increment instead of post - now the same as iota. Added a test for 0 as well. [SVN r85465] --- include/boost/algorithm/cxx11/iota.hpp | 4 ++-- test/iota_test1.cpp | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/boost/algorithm/cxx11/iota.hpp b/include/boost/algorithm/cxx11/iota.hpp index b4f0daf..eb32390 100644 --- a/include/boost/algorithm/cxx11/iota.hpp +++ b/include/boost/algorithm/cxx11/iota.hpp @@ -63,8 +63,8 @@ void iota ( Range &r, T value ) template OutputIterator iota_n ( OutputIterator out, T value, std::size_t n ) { - while ( n-- > 0 ) - *out++ = value++; + for ( ; n > 0; --n, ++value ) + *out++ = value; return out; } diff --git a/test/iota_test1.cpp b/test/iota_test1.cpp index 080d3d7..747691f 100644 --- a/test/iota_test1.cpp +++ b/test/iota_test1.cpp @@ -42,11 +42,11 @@ void test_ints () { std::vector v; std::list l; - v.clear (); v.reserve ( 10 ); + v.clear (); v.resize ( 10 ); boost::algorithm::iota ( v.begin (), v.end (), 23 ); BOOST_CHECK ( test_iota_results ( v.begin (), v.end (), 23 )); - v.clear (); v.reserve ( 19 ); + v.clear (); v.resize ( 19 ); boost::algorithm::iota ( v, 18 ); BOOST_CHECK ( test_iota_results ( v, 18 )); @@ -54,6 +54,10 @@ void test_ints () { boost::algorithm::iota_n ( std::back_inserter(v), 99, 20 ); BOOST_CHECK ( test_iota_results ( v, 99 )); + v.clear (); + boost::algorithm::iota_n ( std::back_inserter(v), 99, 0 ); + BOOST_CHECK ( v.size() == 0 ); + /* l.clear (); l.reserve ( 5 ); boost::algorithm::iota ( l.begin (), l.end (), 123 ); From d528574fe9c6d0b888cc05865ac320c03943447e Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Tue, 17 Sep 2013 20:37:20 +0000 Subject: [PATCH 10/17] To reduce dependencies changed includes from iterator_range.hpp to iterator_range_core.hpp. [SVN r85731] --- include/boost/algorithm/string/concept.hpp | 2 +- include/boost/algorithm/string/detail/find_format.hpp | 2 +- include/boost/algorithm/string/detail/find_format_all.hpp | 2 +- include/boost/algorithm/string/detail/find_format_store.hpp | 2 +- include/boost/algorithm/string/detail/find_iterator.hpp | 2 +- include/boost/algorithm/string/detail/finder.hpp | 2 +- include/boost/algorithm/string/detail/finder_regex.hpp | 2 +- include/boost/algorithm/string/detail/formatter.hpp | 2 +- include/boost/algorithm/string/detail/util.hpp | 2 +- include/boost/algorithm/string/erase.hpp | 2 +- include/boost/algorithm/string/find.hpp | 2 +- include/boost/algorithm/string/find_format.hpp | 2 +- include/boost/algorithm/string/find_iterator.hpp | 2 +- include/boost/algorithm/string/finder.hpp | 2 +- include/boost/algorithm/string/formatter.hpp | 2 +- include/boost/algorithm/string/iter_find.hpp | 2 +- include/boost/algorithm/string/predicate.hpp | 2 +- include/boost/algorithm/string/regex.hpp | 2 +- include/boost/algorithm/string/replace.hpp | 2 +- include/boost/algorithm/string/trim.hpp | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) diff --git a/include/boost/algorithm/string/concept.hpp b/include/boost/algorithm/string/concept.hpp index 9876e98..17e8349 100644 --- a/include/boost/algorithm/string/concept.hpp +++ b/include/boost/algorithm/string/concept.hpp @@ -12,7 +12,7 @@ #define BOOST_STRING_CONCEPT_HPP #include -#include +#include #include #include diff --git a/include/boost/algorithm/string/detail/find_format.hpp b/include/boost/algorithm/string/detail/find_format.hpp index 1612b93..b398750 100644 --- a/include/boost/algorithm/string/detail/find_format.hpp +++ b/include/boost/algorithm/string/detail/find_format.hpp @@ -12,7 +12,7 @@ #define BOOST_STRING_FIND_FORMAT_DETAIL_HPP #include -#include +#include #include #include #include diff --git a/include/boost/algorithm/string/detail/find_format_all.hpp b/include/boost/algorithm/string/detail/find_format_all.hpp index 51ad566..52930c8 100644 --- a/include/boost/algorithm/string/detail/find_format_all.hpp +++ b/include/boost/algorithm/string/detail/find_format_all.hpp @@ -12,7 +12,7 @@ #define BOOST_STRING_FIND_FORMAT_ALL_DETAIL_HPP #include -#include +#include #include #include #include diff --git a/include/boost/algorithm/string/detail/find_format_store.hpp b/include/boost/algorithm/string/detail/find_format_store.hpp index e8bd84a..b9f4a88 100644 --- a/include/boost/algorithm/string/detail/find_format_store.hpp +++ b/include/boost/algorithm/string/detail/find_format_store.hpp @@ -12,7 +12,7 @@ #define BOOST_STRING_FIND_FORMAT_STORE_DETAIL_HPP #include -#include +#include namespace boost { namespace algorithm { diff --git a/include/boost/algorithm/string/detail/find_iterator.hpp b/include/boost/algorithm/string/detail/find_iterator.hpp index c76993a..9b78a0f 100644 --- a/include/boost/algorithm/string/detail/find_iterator.hpp +++ b/include/boost/algorithm/string/detail/find_iterator.hpp @@ -12,7 +12,7 @@ #define BOOST_STRING_FIND_ITERATOR_DETAIL_HPP #include -#include +#include #include #include #include diff --git a/include/boost/algorithm/string/detail/finder.hpp b/include/boost/algorithm/string/detail/finder.hpp index 40112dd..209ce0b 100644 --- a/include/boost/algorithm/string/detail/finder.hpp +++ b/include/boost/algorithm/string/detail/finder.hpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/boost/algorithm/string/detail/finder_regex.hpp b/include/boost/algorithm/string/detail/finder_regex.hpp index 01bf5a0..9cb01cf 100644 --- a/include/boost/algorithm/string/detail/finder_regex.hpp +++ b/include/boost/algorithm/string/detail/finder_regex.hpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include diff --git a/include/boost/algorithm/string/detail/formatter.hpp b/include/boost/algorithm/string/detail/formatter.hpp index 8e7b727..c071822 100644 --- a/include/boost/algorithm/string/detail/formatter.hpp +++ b/include/boost/algorithm/string/detail/formatter.hpp @@ -12,7 +12,7 @@ #define BOOST_STRING_FORMATTER_DETAIL_HPP -#include +#include #include #include #include diff --git a/include/boost/algorithm/string/detail/util.hpp b/include/boost/algorithm/string/detail/util.hpp index 7e8471f..cf4a8b1 100644 --- a/include/boost/algorithm/string/detail/util.hpp +++ b/include/boost/algorithm/string/detail/util.hpp @@ -13,7 +13,7 @@ #include #include -#include +#include namespace boost { namespace algorithm { diff --git a/include/boost/algorithm/string/erase.hpp b/include/boost/algorithm/string/erase.hpp index e738b86..6883790 100644 --- a/include/boost/algorithm/string/erase.hpp +++ b/include/boost/algorithm/string/erase.hpp @@ -13,7 +13,7 @@ #include -#include +#include #include #include #include diff --git a/include/boost/algorithm/string/find.hpp b/include/boost/algorithm/string/find.hpp index da1cb61..f2c2926 100644 --- a/include/boost/algorithm/string/find.hpp +++ b/include/boost/algorithm/string/find.hpp @@ -13,7 +13,7 @@ #include -#include +#include #include #include #include diff --git a/include/boost/algorithm/string/find_format.hpp b/include/boost/algorithm/string/find_format.hpp index ef03739..0e84a4e 100644 --- a/include/boost/algorithm/string/find_format.hpp +++ b/include/boost/algorithm/string/find_format.hpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/boost/algorithm/string/find_iterator.hpp b/include/boost/algorithm/string/find_iterator.hpp index e8cede5..bba1748 100644 --- a/include/boost/algorithm/string/find_iterator.hpp +++ b/include/boost/algorithm/string/find_iterator.hpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/boost/algorithm/string/finder.hpp b/include/boost/algorithm/string/finder.hpp index 4c7ac38..93f7ec3 100644 --- a/include/boost/algorithm/string/finder.hpp +++ b/include/boost/algorithm/string/finder.hpp @@ -13,7 +13,7 @@ #include -#include +#include #include #include #include diff --git a/include/boost/algorithm/string/formatter.hpp b/include/boost/algorithm/string/formatter.hpp index c2c13eb..de8681b 100644 --- a/include/boost/algorithm/string/formatter.hpp +++ b/include/boost/algorithm/string/formatter.hpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include diff --git a/include/boost/algorithm/string/iter_find.hpp b/include/boost/algorithm/string/iter_find.hpp index e106528..10424ab 100644 --- a/include/boost/algorithm/string/iter_find.hpp +++ b/include/boost/algorithm/string/iter_find.hpp @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/boost/algorithm/string/predicate.hpp b/include/boost/algorithm/string/predicate.hpp index 6642f42..0879829 100644 --- a/include/boost/algorithm/string/predicate.hpp +++ b/include/boost/algorithm/string/predicate.hpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include diff --git a/include/boost/algorithm/string/regex.hpp b/include/boost/algorithm/string/regex.hpp index 0a4c38b..a6c7c60 100644 --- a/include/boost/algorithm/string/regex.hpp +++ b/include/boost/algorithm/string/regex.hpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/boost/algorithm/string/replace.hpp b/include/boost/algorithm/string/replace.hpp index f2d201f..0c04e47 100644 --- a/include/boost/algorithm/string/replace.hpp +++ b/include/boost/algorithm/string/replace.hpp @@ -13,7 +13,7 @@ #include -#include +#include #include #include #include diff --git a/include/boost/algorithm/string/trim.hpp b/include/boost/algorithm/string/trim.hpp index be57cd9..e740d57 100644 --- a/include/boost/algorithm/string/trim.hpp +++ b/include/boost/algorithm/string/trim.hpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include From 083c6f58918b08699ec90883c0c01820b650b59e Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 30 Sep 2013 00:18:17 +0000 Subject: [PATCH 11/17] Algorithm: Remove obsolete MSVC version checks. [SVN r86024] --- include/boost/algorithm/string/detail/finder.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/boost/algorithm/string/detail/finder.hpp b/include/boost/algorithm/string/detail/finder.hpp index 209ce0b..a2a9582 100644 --- a/include/boost/algorithm/string/detail/finder.hpp +++ b/include/boost/algorithm/string/detail/finder.hpp @@ -622,8 +622,6 @@ namespace boost { { #if BOOST_WORKAROUND( __MWERKS__, <= 0x3003 ) return iterator_range(this->m_Range); -#elif BOOST_WORKAROUND(BOOST_MSVC, <= 1300) - return iterator_range(m_Range.begin(), m_Range.end()); #else return m_Range; #endif From 4b9a073780482cb96704035c6f3f11d17dd70123 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Sun, 6 Oct 2013 01:24:41 +0000 Subject: [PATCH 12/17] Fixed typo in documentation for equal and mismatch; thanks to Larry for the catch [SVN r86171] --- doc/equal.qbk | 2 +- doc/mismatch.qbk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/equal.qbk b/doc/equal.qbk index 859a8a1..0ba221c 100644 --- a/doc/equal.qbk +++ b/doc/equal.qbk @@ -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 (), seq1.begin (), seq2.end ()); // false + std::equal ( seq1.begin (), seq1.end (), seq2.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). diff --git a/doc/mismatch.qbk b/doc/mismatch.qbk index 630bdc1..cf74293 100644 --- a/doc/mismatch.qbk +++ b/doc/mismatch.qbk @@ -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 (), seq1.begin (), seq2.end ()); // <3, 3> + std::mismatch ( seq1.begin (), seq1.end (), seq2.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). From b44dff3a5bd07a534aa9885b64b80e9fcc57338b Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Tue, 8 Oct 2013 17:59:44 +0000 Subject: [PATCH 13/17] Revert to old behavior for find_iterator; will not find overlapping matches. Fixes #9063 [SVN r86206] --- .../boost/algorithm/string/find_iterator.hpp | 7 +---- string/test/find_test.cpp | 28 ++++++++++--------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/include/boost/algorithm/string/find_iterator.hpp b/include/boost/algorithm/string/find_iterator.hpp index bba1748..1502c7d 100644 --- a/include/boost/algorithm/string/find_iterator.hpp +++ b/include/boost/algorithm/string/find_iterator.hpp @@ -132,12 +132,7 @@ namespace boost { // increment void increment() { - 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); - } + m_Match=this->do_find(m_Match.end(),m_End); } // comparison diff --git a/string/test/find_test.cpp b/string/test/find_test.cpp index 85facb0..66d9337 100644 --- a/string/test/find_test.cpp +++ b/string/test/find_test.cpp @@ -181,6 +181,21 @@ void find_test() ( (cv_result.begin()-str1.begin()) == 3) && ( (cv_result.end()-str1.begin()) == 6) ); + string s1("abc def ghi jkl"); + find_iterator fEnd; + + find_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) && @@ -251,19 +266,6 @@ 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 > 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 From 432b3a3da003a63db6c8d08682af704ba11e4c2c Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 11 Oct 2013 23:13:10 +0000 Subject: [PATCH 14/17] Remove BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION Process #ifdef...#endif blocks. [SVN r86243] --- .../algorithm/string/sequence_traits.hpp | 41 ------------------- 1 file changed, 41 deletions(-) diff --git a/include/boost/algorithm/string/sequence_traits.hpp b/include/boost/algorithm/string/sequence_traits.hpp index b1ac67e..ed9d32c 100644 --- a/include/boost/algorithm/string/sequence_traits.hpp +++ b/include/boost/algorithm/string/sequence_traits.hpp @@ -36,47 +36,6 @@ 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 /*! From ef78dde4485216cffbbca3469d296a715ca14e8f Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 11 Oct 2013 23:19:17 +0000 Subject: [PATCH 15/17] Remove BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION Process #ifdef...#else...#endif blocks. [SVN r86246] --- .../algorithm/string/sequence_traits.hpp | 32 ------------------- .../algorithm/string/std/list_traits.hpp | 17 ---------- .../algorithm/string/std/rope_traits.hpp | 20 ------------ .../algorithm/string/std/slist_traits.hpp | 16 ---------- .../algorithm/string/std/string_traits.hpp | 8 ----- 5 files changed, 93 deletions(-) diff --git a/include/boost/algorithm/string/sequence_traits.hpp b/include/boost/algorithm/string/sequence_traits.hpp index ed9d32c..be151f8 100644 --- a/include/boost/algorithm/string/sequence_traits.hpp +++ b/include/boost/algorithm/string/sequence_traits.hpp @@ -45,20 +45,12 @@ 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_::value> type; @@ -73,20 +65,12 @@ 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_::value> type; }; @@ -100,20 +84,12 @@ 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_::value> type; }; @@ -127,20 +103,12 @@ 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_::value> type; }; diff --git a/include/boost/algorithm/string/std/list_traits.hpp b/include/boost/algorithm/string/std/list_traits.hpp index ce2379d..a3cf7bb 100644 --- a/include/boost/algorithm/string/std/list_traits.hpp +++ b/include/boost/algorithm/string/std/list_traits.hpp @@ -20,22 +20,6 @@ namespace boost { // std::list<> traits -----------------------------------------------// -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - - // stable iterators tester - template - yes_type has_stable_iterators_tester( const ::std::list* ); - - // const time insert tester - template - yes_type has_const_time_insert_tester( const ::std::list* ); - - // const time erase tester - template - yes_type has_const_time_erase_tester( const ::std::list* ); - - -#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // stable iterators trait template @@ -75,7 +59,6 @@ namespace boost { #endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) typedef mpl::bool_::value> type; }; -#endif } // namespace algorithm diff --git a/include/boost/algorithm/string/std/rope_traits.hpp b/include/boost/algorithm/string/std/rope_traits.hpp index c2cd549..637059a 100644 --- a/include/boost/algorithm/string/std/rope_traits.hpp +++ b/include/boost/algorithm/string/std/rope_traits.hpp @@ -20,25 +20,6 @@ namespace boost { // SGI's std::rope<> traits -----------------------------------------------// -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - - // native replace tester - template - yes_type has_native_replace_tester( const std::rope* ); - - // stable iterators tester - template - yes_type has_stable_iterators_tester( const std::rope* ); - - // const time insert tester - template - yes_type has_const_time_insert_tester( const std::rope* ); - - // const time erase tester - template - yes_type has_const_time_erase_tester( const std::rope* ); - -#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // native replace trait template @@ -91,7 +72,6 @@ namespace boost { #endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) typedef mpl::bool_ type; }; -#endif } // namespace algorithm diff --git a/include/boost/algorithm/string/std/slist_traits.hpp b/include/boost/algorithm/string/std/slist_traits.hpp index 7b915a3..c30b93c 100644 --- a/include/boost/algorithm/string/std/slist_traits.hpp +++ b/include/boost/algorithm/string/std/slist_traits.hpp @@ -21,21 +21,6 @@ namespace boost { // SGI's std::slist<> traits -----------------------------------------------// -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - - // stable iterators tester - template - yes_type has_stable_iterators_tester( const BOOST_STD_EXTENSION_NAMESPACE::slist* ); - - // const time insert tester - template - yes_type has_const_time_insert_tester( const BOOST_STD_EXTENSION_NAMESPACE::slist* ); - - // const time erase tester - template - yes_type has_const_time_erase_tester( const BOOST_STD_EXTENSION_NAMESPACE::slist* ); - -#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // stable iterators trait template @@ -75,7 +60,6 @@ namespace boost { #endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) typedef mpl::bool_::value> type; }; -#endif } // namespace algorithm diff --git a/include/boost/algorithm/string/std/string_traits.hpp b/include/boost/algorithm/string/std/string_traits.hpp index c466d26..c940830 100644 --- a/include/boost/algorithm/string/std/string_traits.hpp +++ b/include/boost/algorithm/string/std/string_traits.hpp @@ -20,13 +20,6 @@ namespace boost { // std::basic_string<> traits -----------------------------------------------// -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - - // native replace tester - template - yes_type has_native_replace_tester( const std::basic_string* ); - -#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // native replace trait template @@ -43,7 +36,6 @@ namespace boost { }; -#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION } // namespace algorithm } // namespace boost From 4c3b17ce7767ce21533dc65c76774ba3d2b2b41f Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Mon, 14 Oct 2013 21:31:19 +0000 Subject: [PATCH 16/17] Remove tabs [SVN r86310] --- include/boost/algorithm/cxx14/equal.hpp | 80 +++++++++++----------- include/boost/algorithm/cxx14/mismatch.hpp | 16 ++--- string/test/find_test.cpp | 26 +++---- string/test/split_test.cpp | 4 +- test/iterator_test.hpp | 20 +++--- 5 files changed, 73 insertions(+), 73 deletions(-) diff --git a/include/boost/algorithm/cxx14/equal.hpp b/include/boost/algorithm/cxx14/equal.hpp index d10c096..cfc62d5 100644 --- a/include/boost/algorithm/cxx14/equal.hpp +++ b/include/boost/algorithm/cxx14/equal.hpp @@ -12,41 +12,41 @@ #ifndef BOOST_ALGORITHM_EQUAL_HPP #define BOOST_ALGORITHM_EQUAL_HPP -#include // for std::equal -#include // for std::equal_to +#include // for std::equal +#include // for std::equal_to namespace boost { namespace algorithm { namespace detail { - template - struct eq : public std::binary_function { - bool operator () ( const T1& v1, const T2& v2 ) const { return v1 == v2 ;} - }; - - template - 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 + struct eq : public std::binary_function { + bool operator () ( const T1& v1, const T2& v2 ) const { return v1 == v2 ;} + }; + + template + 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 - 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 + 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 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::iterator_category (), - typename std::iterator_traits::iterator_category ()); + return boost::algorithm::detail::equal ( + first1, last1, first2, last2, pred, + typename std::iterator_traits::iterator_category (), + typename std::iterator_traits::iterator_category ()); } /// \fn equal ( InputIterator1 first1, InputIterator1 last1, @@ -81,16 +81,16 @@ template 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::value_type, - typename std::iterator_traits::value_type> (), - typename std::iterator_traits::iterator_category (), - typename std::iterator_traits::iterator_category ()); + return boost::algorithm::detail::equal ( + first1, last1, first2, last2, + boost::algorithm::detail::eq< + typename std::iterator_traits::value_type, + typename std::iterator_traits::value_type> (), + typename std::iterator_traits::iterator_category (), + typename std::iterator_traits::iterator_category ()); } -// There are already range-based versions of these. +// There are already range-based versions of these. }} // namespace boost and algorithm diff --git a/include/boost/algorithm/cxx14/mismatch.hpp b/include/boost/algorithm/cxx14/mismatch.hpp index c45fded..926ab19 100644 --- a/include/boost/algorithm/cxx14/mismatch.hpp +++ b/include/boost/algorithm/cxx14/mismatch.hpp @@ -12,8 +12,8 @@ #ifndef BOOST_ALGORITHM_MISMATCH_HPP #define BOOST_ALGORITHM_MISMATCH_HPP -#include // for std::mismatch -#include // for std::pair +#include // for std::mismatch +#include // 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 std::pair 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 mismatch ( /// \param last2 One past the end of the second range. template std::pair 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 mismatch ( return std::pair(first1, first2); } -// There are already range-based versions of these. +// There are already range-based versions of these. }} // namespace boost and algorithm diff --git a/string/test/find_test.cpp b/string/test/find_test.cpp index 66d9337..8439b3c 100644 --- a/string/test/find_test.cpp +++ b/string/test/find_test.cpp @@ -181,20 +181,20 @@ void find_test() ( (cv_result.begin()-str1.begin()) == 3) && ( (cv_result.end()-str1.begin()) == 6) ); - string s1("abc def ghi jkl"); - find_iterator fEnd; + string s1("abc def ghi jkl"); + find_iterator fEnd; - find_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); + find_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( diff --git a/string/test/split_test.cpp b/string/test/split_test.cpp index 429f3c4..582472b 100644 --- a/string/test/split_test.cpp +++ b/string/test/split_test.cpp @@ -46,7 +46,7 @@ void iterator_test() const char* pch1="xx-abc--xx-abb"; vector tokens; vector< vector > vtokens; - + // find_all tests find_all( tokens, @@ -182,7 +182,7 @@ void iterator_test() BOOST_CHECK(siter==split_iterator()); // Make sure we work with forward iterators -// See bug #7989 +// See bug #7989 list l1; find_iterator::iterator> liter=make_find_iterator(l1, first_finder("xx")); } diff --git a/test/iterator_test.hpp b/test/iterator_test.hpp index cd77fb6..b3ba064 100644 --- a/test/iterator_test.hpp +++ b/test/iterator_test.hpp @@ -2,11 +2,11 @@ #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 @@ -269,10 +269,10 @@ public: private: It it_; template 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 @@ -290,7 +290,7 @@ inline Iter base(bidirectional_iterator i) { return i.base(); } template inline Iter base(random_access_iterator i) { return i.base(); } -template // everything else +template // everything else inline Iter base(Iter i) { return i; } #endif // ITERATORS_H From 617ec039375608abe12f2a172b09f35c4c11300f Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Mon, 14 Oct 2013 21:35:20 +0000 Subject: [PATCH 17/17] Updated license and copyright [SVN r86311] --- test/iterator_test.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/iterator_test.hpp b/test/iterator_test.hpp index b3ba064..a79e7cf 100644 --- a/test/iterator_test.hpp +++ b/test/iterator_test.hpp @@ -1,3 +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