From c6f784cb7034b0a8c3183086fcd7ed8389e50a03 Mon Sep 17 00:00:00 2001 From: Ben10do Date: Wed, 1 Aug 2018 20:54:17 +0100 Subject: [PATCH 1/5] Use forwarding references in string/split.hpp On compilers that support C++11, this allows both lvalues and rvalues to be used as inputs to the split(), find_all(), and ifind_all() functions. For example, given a function get_string() that returns a std::string, this allows you to write: boost::split(result, get_string(), boost::is_any_of(" ")) --- include/boost/algorithm/string/iter_find.hpp | 8 ++++++++ include/boost/algorithm/string/split.hpp | 12 ++++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/boost/algorithm/string/iter_find.hpp b/include/boost/algorithm/string/iter_find.hpp index 10424ab..d76a819 100644 --- a/include/boost/algorithm/string/iter_find.hpp +++ b/include/boost/algorithm/string/iter_find.hpp @@ -71,7 +71,11 @@ namespace boost { inline SequenceSequenceT& iter_find( SequenceSequenceT& Result, +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + RangeT&& Input, +#else RangeT& Input, +#endif FinderT Finder ) { BOOST_CONCEPT_ASSERT(( @@ -142,7 +146,11 @@ namespace boost { inline SequenceSequenceT& iter_split( SequenceSequenceT& Result, +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + RangeT&& Input, +#else RangeT& Input, +#endif FinderT Finder ) { BOOST_CONCEPT_ASSERT(( diff --git a/include/boost/algorithm/string/split.hpp b/include/boost/algorithm/string/split.hpp index cae712c..e0b30fb 100644 --- a/include/boost/algorithm/string/split.hpp +++ b/include/boost/algorithm/string/split.hpp @@ -61,7 +61,11 @@ namespace boost { template< typename SequenceSequenceT, typename Range1T, typename Range2T > inline SequenceSequenceT& find_all( SequenceSequenceT& Result, +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + Range1T&& Input, +#else Range1T& Input, +#endif const Range2T& Search) { return ::boost::algorithm::iter_find( @@ -96,7 +100,11 @@ namespace boost { template< typename SequenceSequenceT, typename Range1T, typename Range2T > inline SequenceSequenceT& ifind_all( SequenceSequenceT& Result, +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + Range1T&& Input, +#else Range1T& Input, +#endif const Range2T& Search, const std::locale& Loc=std::locale() ) { @@ -139,7 +147,11 @@ namespace boost { template< typename SequenceSequenceT, typename RangeT, typename PredicateT > inline SequenceSequenceT& split( SequenceSequenceT& Result, +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + RangeT&& Input, +#else RangeT& Input, +#endif PredicateT Pred, token_compress_mode_type eCompress=token_compress_off ) { From 5408a17020ba7d7467288ce59f820a07ae890142 Mon Sep 17 00:00:00 2001 From: Ben10do Date: Wed, 1 Aug 2018 22:42:18 +0100 Subject: [PATCH 2/5] Add tests with lvalue inputs If the compiler supports forwarding references, we now test if lvalues can be used as input strings for split(), find_all(), and ifind_all(). Note that MSVC (without its recent /permissive- flag) may pass these tests without the forwarding references changes that I made, due to its non-standard binding of lvalues to rvalues. --- string/test/split_test.cpp | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/string/test/split_test.cpp b/string/test/split_test.cpp index 582472b..d7e9186 100644 --- a/string/test/split_test.cpp +++ b/string/test/split_test.cpp @@ -7,6 +7,8 @@ // See http://www.boost.org for updates, documentation, and revision history. +#include + #include #include // equals predicate is used for result comparison @@ -82,6 +84,28 @@ void iterator_test() string("xx") ); deep_compare( tokens, vtokens ); +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + // If using a compiler that supports forwarding references, we should be able to use lvalues, too + find_all( + tokens, + string("xx-abc--xx-abb"), + "xx" ); + + BOOST_REQUIRE( tokens.size()==2 ); + BOOST_CHECK( tokens[0]==string("xx") ); + BOOST_CHECK( tokens[1]==string("xx") ); + + ifind_all( + tokens, + string("Xx-abc--xX-abb-xx"), + "xx" ); + + BOOST_REQUIRE( tokens.size()==3 ); + BOOST_CHECK( tokens[0]==string("Xx") ); + BOOST_CHECK( tokens[1]==string("xX") ); + BOOST_CHECK( tokens[2]==string("xx") ); +#endif + // split tests split( tokens, @@ -144,6 +168,21 @@ void iterator_test() BOOST_REQUIRE( tokens.size()==1 ); BOOST_CHECK( tokens[0]==string("") ); +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + // If using a compiler that supports forwarding references, we should be able to use lvalues, too + split( + tokens, + string("Xx-abc--xX-abb-xx"), + is_any_of("xX"), + token_compress_on ); + + BOOST_REQUIRE( tokens.size()==4 ); + BOOST_CHECK( tokens[0]==string("") ); + BOOST_CHECK( tokens[1]==string("-abc--") ); + BOOST_CHECK( tokens[2]==string("-abb-") ); + BOOST_CHECK( tokens[3]==string("") ); +#endif + find_iterator fiter=make_find_iterator(str1, first_finder("xx")); find_iterator fiter2; From 45baad2431913db14ff0d2d014226985bf3602ae Mon Sep 17 00:00:00 2001 From: Ben10do Date: Thu, 2 Aug 2018 22:18:54 +0100 Subject: [PATCH 3/5] Correct lvalue/rvalue nomenclature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I accidentally referred to the additional tests as using lvalues as inputs, when they’re actually using rvalues. This commit corrects the relevant comments. --- string/test/split_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/string/test/split_test.cpp b/string/test/split_test.cpp index d7e9186..3dbcfac 100644 --- a/string/test/split_test.cpp +++ b/string/test/split_test.cpp @@ -85,7 +85,7 @@ void iterator_test() deep_compare( tokens, vtokens ); #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - // If using a compiler that supports forwarding references, we should be able to use lvalues, too + // If using a compiler that supports forwarding references, we should be able to use rvalues, too find_all( tokens, string("xx-abc--xx-abb"), @@ -169,7 +169,7 @@ void iterator_test() BOOST_CHECK( tokens[0]==string("") ); #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - // If using a compiler that supports forwarding references, we should be able to use lvalues, too + // If using a compiler that supports forwarding references, we should be able to use rvalues, too split( tokens, string("Xx-abc--xX-abb-xx"), From f39107f2289a61ee151387c424d5dd577f5aface Mon Sep 17 00:00:00 2001 From: Tinko Bartels Date: Tue, 23 Apr 2019 13:48:19 +0200 Subject: [PATCH 4/5] Replace broken links. --- include/boost/algorithm/find_backward.hpp | 2 +- include/boost/algorithm/find_not.hpp | 2 +- minmax/doc/minmax_synopsis.html | 38 +++++++++++------------ minmax/index.html | 32 +++++++++---------- string/doc/external_concepts.html | 2 +- 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/include/boost/algorithm/find_backward.hpp b/include/boost/algorithm/find_backward.hpp index 66901a1..6102c9a 100644 --- a/include/boost/algorithm/find_backward.hpp +++ b/include/boost/algorithm/find_backward.hpp @@ -2,7 +2,7 @@ Copyright (c) T. Zachary Laine 2018. Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt) + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #ifndef BOOST_ALGORITHM_FIND_BACKWARD_HPP #define BOOST_ALGORITHM_FIND_BACKWARD_HPP diff --git a/include/boost/algorithm/find_not.hpp b/include/boost/algorithm/find_not.hpp index ef4df00..4d8a28a 100644 --- a/include/boost/algorithm/find_not.hpp +++ b/include/boost/algorithm/find_not.hpp @@ -2,7 +2,7 @@ Copyright (c) T. Zachary Laine 2018. Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt) + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #ifndef BOOST_ALGORITHM_FIND_NOT_HPP #define BOOST_ALGORITHM_FIND_NOT_HPP diff --git a/minmax/doc/minmax_synopsis.html b/minmax/doc/minmax_synopsis.html index 1651a13..09b64f8 100644 --- a/minmax/doc/minmax_synopsis.html +++ b/minmax/doc/minmax_synopsis.html @@ -24,7 +24,7 @@ namespace boost { tuple<T const&, T const&> > minmax(const T& a, const T& b); - template <class T, class BinaryPredicate> + template <class T, class BinaryPredicate> tuple<T const&, T const&> > minmax(const T& a, const T& b, BinaryPredicate comp); @@ -38,77 +38,77 @@ Synopsis of <boost/algorithm/minmax_element.hpp> namespace boost { - template <class ForwardIterator> + template <class ForwardIterator> std::pair<ForwardIterator,ForwardIterator> minmax_element(ForwardIterator first, ForwardIterator last); - template <class ForwardIterator, class BinaryPredicate> + template <class ForwardIterator, class BinaryPredicate> std::pair<ForwardIterator,ForwardIterator> minmax_element(ForwardIterator first, ForwardIterator last, BinaryPredicate comp); // Variants - template <class ForwardIterator> + template <class ForwardIterator> ForwardIterator first_min_element(ForwardIterator first, ForwardIterator last); - template <class ForwardIterator, class BinaryPredicate> + template <class ForwardIterator, class BinaryPredicate> ForwardIterator first_min_element(ForwardIterator first, ForwardIterator last, BinaryPredicate comp); - template <class ForwardIterator> + template <class ForwardIterator> ForwardIterator last_min_element(ForwardIterator first, ForwardIterator last); - template <class ForwardIterator, class BinaryPredicate> + template <class ForwardIterator, class BinaryPredicate> ForwardIterator last_min_element(ForwardIterator first, ForwardIterator last, BinaryPredicate comp); - template <class ForwardIterator> + template <class ForwardIterator> ForwardIterator first_max_element(ForwardIterator first, ForwardIterator last); - template <class ForwardIterator, class BinaryPredicate> + template <class ForwardIterator, class BinaryPredicate> ForwardIterator first_max_element(ForwardIterator first, ForwardIterator last, BinaryPredicate comp); - template <class ForwardIterator> + template <class ForwardIterator> ForwardIterator last_max_element(ForwardIterator first, ForwardIterator last); - template <class ForwardIterator, class BinaryPredicate> + template <class ForwardIterator, class BinaryPredicate> ForwardIterator last_max_element(ForwardIterator first, ForwardIterator last, BinaryPredicate comp); - template <class ForwardIterator> + template <class ForwardIterator> std::pair<ForwardIterator,ForwardIterator> first_min_first_max_element(ForwardIterator first, ForwardIterator last); - template <class ForwardIterator, class BinaryPredicate> + template <class ForwardIterator, class BinaryPredicate> std::pair<ForwardIterator,ForwardIterator> first_min_first_max_element(ForwardIterator first, ForwardIterator last, BinaryPredicate comp); - template <class ForwardIterator> + template <class ForwardIterator> std::pair<ForwardIterator,ForwardIterator> first_min_last_max_element(ForwardIterator first, ForwardIterator last); - template <class ForwardIterator, class BinaryPredicate> + template <class ForwardIterator, class BinaryPredicate> std::pair<ForwardIterator,ForwardIterator> first_min_last_max_element(ForwardIterator first, ForwardIterator last, BinaryPredicate comp); - template <class ForwardIterator> + template <class ForwardIterator> std::pair<ForwardIterator,ForwardIterator> last_min_first_max_element(ForwardIterator first, ForwardIterator last); - template <class ForwardIterator, class BinaryPredicate> + template <class ForwardIterator, class BinaryPredicate> std::pair<ForwardIterator,ForwardIterator> last_min_first_max_element(ForwardIterator first, ForwardIterator last, BinaryPredicate comp); - template <class ForwardIterator> + template <class ForwardIterator> std::pair<ForwardIterator,ForwardIterator> last_min_last_max_element(ForwardIterator first, ForwardIterator last); - template <class ForwardIterator, class BinaryPredicate> + template <class ForwardIterator, class BinaryPredicate> std::pair<ForwardIterator,ForwardIterator> last_min_last_max_element(ForwardIterator first, ForwardIterator last, BinaryPredicate comp); diff --git a/minmax/index.html b/minmax/index.html index 72a5116..f58bfe6 100644 --- a/minmax/index.html +++ b/minmax/index.html @@ -95,7 +95,7 @@ namespace boost { tuple<T const&, T const&> minmax(const T& a, const T& b); - template <class T, class BinaryPredicate> + template <class T, class BinaryPredicate> tuple<T const&, T const&> minmax(const T& a, const T& b, BinaryPredicate comp); @@ -109,11 +109,11 @@ Synopsis of <boost/algorithm/minmax_element.hpp> namespace boost { - template <class ForwardIterator> + template <class ForwardIterator> std::pair<ForwardIterator,ForwardIterator> minmax_element(ForwardIterator first, ForwardIterator last); - template <class ForwardIterator, class BinaryPredicate> + template <class ForwardIterator, class BinaryPredicate> std::pair<ForwardIterator,ForwardIterator> minmax_element(ForwardIterator first, ForwardIterator last, BinaryPredicate comp); @@ -190,26 +190,26 @@ in minmax_element.hpp.

Requirements on types

-For minmax, T must be a model of
LessThan +For minmax, T must be a model of LessThan Comparable.

For all the other function templates, versions with two template parameters:

For the versions with three template parameters:
  • -ForwardIterator is a model of Forward +ForwardIterator is a model of Forward Iterator.
  • -BinaryPredicate is a model of Binary +BinaryPredicate is a model of Binary Predicate.
  • @@ -285,8 +285,8 @@ the library under assert( result1.get<0>() == 0 ); assert( result1.get<1>() == 1 ); - list<int> L; - generate_n(front_inserter(L), 1000, rand); + list<int> L; + generate_n(front_inserter(L), 1000, rand); typedef list<int>::const_iterator iterator; pair< iterator, iterator > result2 = boost::minmax_element(L.begin(), L.end()); @@ -512,13 +512,13 @@ release, Eric Niebler noted the bad behavior of std::pair for All my thanks for the excellent advice and reviews from all.

    See also

    -min, max, -min_element, -max_element, -LessThan +min, max, +min_element, +max_element, +LessThan Comparable, -sort, -nth_element +sort, +nth_element .

    Last modified 2012-12-10 diff --git a/string/doc/external_concepts.html b/string/doc/external_concepts.html index af403be..679573f 100644 --- a/string/doc/external_concepts.html +++ b/string/doc/external_concepts.html @@ -31,7 +31,7 @@ typedef implementation defined foo_type;

    The corresponding external concept is the ExternalFooConcept.

    A type T fullfills the ExternalFooConcept if these free-standing functions and type-generators exists:

    void foo( const T&, int );
    int bar( T& );
    - foo_type_of< T >::type;



    Literature


    © Thorsten Ottosen 2003-2004 (nesotto_AT_cs.auc.dk). + foo_type_of< T >::type;


    Literature


    © Thorsten Ottosen 2003-2004 (nesotto_AT_cs.auc.dk).
    Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) From 0a57ec30a2bc889bfcbbdb9df901125f50d81516 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Wed, 3 Jul 2019 07:44:25 -0700 Subject: [PATCH 5/5] Update the apply_permutation tests to use the BOOST_CHECK_EQUAL_COLLECTIONS facilities. Based on https://github.com/boostorg/algorithm/pull/42 Thanks to Jeremy for the patch --- test/apply_permutation_test.cpp | 40 ++++++++++++++------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/test/apply_permutation_test.cpp b/test/apply_permutation_test.cpp index 3dbb7e1..94a60ac 100644 --- a/test/apply_permutation_test.cpp +++ b/test/apply_permutation_test.cpp @@ -14,19 +14,19 @@ #define BOOST_TEST_MAIN -#include +#include namespace ba = boost::algorithm; -void test_apply_permutation() +BOOST_AUTO_TEST_CASE(test_apply_permutation) { //Empty { std::vector vec, order, result; ba::apply_permutation(vec.begin(), vec.end(), order.begin(), order.end()); - BOOST_CHECK(vec == result); + BOOST_CHECK_EQUAL_COLLECTIONS(vec.begin(), vec.end(), result.begin(), result.end()); } //1 element { @@ -36,7 +36,7 @@ void test_apply_permutation() result = vec; ba::apply_permutation(vec.begin(), vec.end(), order.begin(), order.end()); - BOOST_CHECK(vec == result); + BOOST_CHECK_EQUAL_COLLECTIONS(vec.begin(), vec.end(), result.begin(), result.end()); } //2 elements, no changes { @@ -46,7 +46,7 @@ void test_apply_permutation() result = vec; ba::apply_permutation(vec.begin(), vec.end(), order.begin(), order.end()); - BOOST_CHECK(vec == result); + BOOST_CHECK_EQUAL_COLLECTIONS(vec.begin(), vec.end(), result.begin(), result.end()); } //2 elements, changed { @@ -56,7 +56,7 @@ void test_apply_permutation() result.push_back(2); result.push_back(1); ba::apply_permutation(vec.begin(), vec.end(), order.begin(), order.end()); - BOOST_CHECK(vec == result); + BOOST_CHECK_EQUAL_COLLECTIONS(vec.begin(), vec.end(), result.begin(), result.end()); } //Multiple elements, no changes { @@ -66,7 +66,7 @@ void test_apply_permutation() result = vec; ba::apply_permutation(vec.begin(), vec.end(), order.begin(), order.end()); - BOOST_CHECK(vec == result); + BOOST_CHECK_EQUAL_COLLECTIONS(vec.begin(), vec.end(), result.begin(), result.end()); } //Multiple elements, changed { @@ -76,7 +76,7 @@ void test_apply_permutation() result.push_back(5); result.push_back(4); result.push_back(3); result.push_back(2); result.push_back(1); ba::apply_permutation(vec.begin(), vec.end(), order.begin(), order.end()); - BOOST_CHECK(vec == result); + BOOST_CHECK_EQUAL_COLLECTIONS(vec.begin(), vec.end(), result.begin(), result.end()); } //Just test range interface { @@ -86,18 +86,18 @@ void test_apply_permutation() result = vec; ba::apply_permutation(vec, order); - BOOST_CHECK(vec == result); + BOOST_CHECK_EQUAL_COLLECTIONS(vec.begin(), vec.end(), result.begin(), result.end()); } } -void test_apply_reverse_permutation() +BOOST_AUTO_TEST_CASE(test_apply_reverse_permutation) { //Empty { std::vector vec, order, result; ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin(), order.end()); - BOOST_CHECK(vec == result); + BOOST_CHECK_EQUAL_COLLECTIONS(vec.begin(), vec.end(), result.begin(), result.end()); } //1 element { @@ -107,7 +107,7 @@ void test_apply_reverse_permutation() result = vec; ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin(), order.end()); - BOOST_CHECK(vec == result); + BOOST_CHECK_EQUAL_COLLECTIONS(vec.begin(), vec.end(), result.begin(), result.end()); } //2 elements, no changes { @@ -117,7 +117,7 @@ void test_apply_reverse_permutation() result = vec; ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin(), order.end()); - BOOST_CHECK(vec == result); + BOOST_CHECK_EQUAL_COLLECTIONS(vec.begin(), vec.end(), result.begin(), result.end()); } //2 elements, changed { @@ -127,7 +127,7 @@ void test_apply_reverse_permutation() result.push_back(2); result.push_back(1); ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin(), order.end()); - BOOST_CHECK(vec == result); + BOOST_CHECK_EQUAL_COLLECTIONS(vec.begin(), vec.end(), result.begin(), result.end()); } //Multiple elements, no changes { @@ -137,7 +137,7 @@ void test_apply_reverse_permutation() result = vec; ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin(), order.end()); - BOOST_CHECK(vec == result); + BOOST_CHECK_EQUAL_COLLECTIONS(vec.begin(), vec.end(), result.begin(), result.end()); } //Multiple elements, changed { @@ -147,7 +147,7 @@ void test_apply_reverse_permutation() result.push_back(5); result.push_back(4); result.push_back(3); result.push_back(2); result.push_back(1); ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin(), order.end()); - BOOST_CHECK(vec == result); + BOOST_CHECK_EQUAL_COLLECTIONS(vec.begin(), vec.end(), result.begin(), result.end()); } //Just test range interface { @@ -157,12 +157,6 @@ void test_apply_reverse_permutation() result = vec; ba::apply_reverse_permutation(vec, order); - BOOST_CHECK(vec == result); + BOOST_CHECK_EQUAL_COLLECTIONS(vec.begin(), vec.end(), result.begin(), result.end()); } } - -BOOST_AUTO_TEST_CASE(test_main) -{ - test_apply_permutation(); - test_apply_reverse_permutation(); -}