forked from boostorg/algorithm
Merge pull request #100 from jgopel/copy-if-while
Implement copy_if_while and copy_if_until
This commit is contained in:
@ -216,14 +216,24 @@ See below
|
||||
|
||||
[section:copy_until copy_until ]
|
||||
[*[^[link header.boost.algorithm.cxx11.copy_if_hpp copy_until] ] ]
|
||||
Copy all the elements at the start of the input range that do not satisfy the predicate to the output range
|
||||
Copy all the elements from the start of the input range to the output range until the predicate is satisfied
|
||||
[endsect:copy_until]
|
||||
|
||||
[section:copy_while copy_while ]
|
||||
[*[^[link header.boost.algorithm.cxx11.copy_if_hpp copy_while] ] ]
|
||||
Copy all the elements at the start of the input range that satisfy the predicate to the output range
|
||||
Copy all the elements from the start of the input range to the output range while the predicate is satisfied
|
||||
[endsect:copy_while]
|
||||
|
||||
[section:copy_if_until copy_if_until ]
|
||||
[*[^[link header.boost.algorithm.cxx11.copy_if_hpp copy_if_until ] ]
|
||||
Copy all elements that satisfy the element predicate from the start of the input range to the output range until the termination predicate is satisfied
|
||||
[endsect:copy_if_until]
|
||||
|
||||
[section:copy_if_while copy_if_while ]
|
||||
[*[^[link header.boost.algorithm.cxx11.copy_if_hpp copy_if_while ] ]
|
||||
Copy all elements that satisfy the element predicate from the start of the input range to the output range while the termination predicate is satisfied
|
||||
[endsect:copy_if_while]
|
||||
|
||||
[section:iota_n iota_n ]
|
||||
[*[^[link boost.algorithm.iota_n iota_n] ] ]
|
||||
Write a sequence of n increasing values to an output iterator
|
||||
|
@ -126,6 +126,86 @@ copy_until ( const Range &r, OutputIterator result, Predicate p )
|
||||
return boost::algorithm::copy_until (boost::begin (r), boost::end(r), result, p);
|
||||
}
|
||||
|
||||
/// \fn copy_if_while ( InputIterator first, InputIterator last, OutputIterator result, CopyPredicate copy_pred, TerminatePred term_pred )
|
||||
/// \brief Copies all the elements from the input range that satisfy the
|
||||
/// copy predicate to the output range while the termination predicate is
|
||||
/// satisfied.
|
||||
/// \return The updated output iterator
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param result An output iterator to write the results into
|
||||
/// \param copy_pred A predicate for testing whether to the current element
|
||||
/// \param term_pred A predicate for testing whether to end the copy operation
|
||||
template<typename InputIterator, typename OutputIterator, typename CopyPredicate, typename TerminatePred>
|
||||
BOOST_CXX14_CONSTEXPR std::pair<InputIterator, OutputIterator>
|
||||
copy_if_while ( InputIterator first, InputIterator last, OutputIterator result, CopyPredicate copy_pred, TerminatePred term_pred)
|
||||
{
|
||||
for ( ; first != last && term_pred(*first); ++first ) {
|
||||
if (copy_pred(*first)) {
|
||||
*result++ = *first;
|
||||
}
|
||||
}
|
||||
return std::make_pair(first, result);
|
||||
}
|
||||
|
||||
/// \fn copy_if_while ( const Range& r, OutputIterator result, CopyPredicate copy_pred, TerminatePred term_pred )
|
||||
/// \brief Copies all the elements from the input range that satisfy the
|
||||
/// copy predicate to the output range while the termination predicate is
|
||||
/// satisfied.
|
||||
/// \return The updated output iterator
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param result An output iterator to write the results into
|
||||
/// \param copy_pred A predicate for testing whether to the current element
|
||||
/// \param term_pred A predicate for testing whether to end the copy operation
|
||||
template<typename Range, typename OutputIterator, typename CopyPredicate, typename TerminatePred>
|
||||
BOOST_CXX14_CONSTEXPR std::pair<typename boost::range_iterator<const Range>::type, OutputIterator>
|
||||
copy_if_while ( const Range& r, OutputIterator result, CopyPredicate copy_pred, TerminatePred term_pred)
|
||||
{
|
||||
return boost::algorithm::copy_if_while(boost::begin(r), boost::end(r), result, copy_pred, term_pred);
|
||||
}
|
||||
|
||||
/// \fn copy_if_until ( InputIterator first, InputIterator last, OutputIterator result, CopyPredicate copy_pred, TerminatePred term_pred )
|
||||
/// \brief Copies all the elements from the input range that satisfy the
|
||||
/// copy predicate to the output range until the termination predicate is
|
||||
/// satisfied.
|
||||
/// \return The updated output iterator
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param result An output iterator to write the results into
|
||||
/// \param copy_pred A predicate for testing whether to the current element
|
||||
/// \param term_pred A predicate for testing whether to end the copy operation
|
||||
template<typename InputIterator, typename OutputIterator, typename CopyPredicate, typename TerminatePred>
|
||||
BOOST_CXX14_CONSTEXPR std::pair<InputIterator, OutputIterator>
|
||||
copy_if_until ( InputIterator first, InputIterator last, OutputIterator result, CopyPredicate copy_pred, TerminatePred term_pred)
|
||||
{
|
||||
for ( ; first != last && !term_pred(*first); ++first ) {
|
||||
if (copy_pred(*first)) {
|
||||
*result++ = *first;
|
||||
}
|
||||
}
|
||||
return std::make_pair(first, result);
|
||||
}
|
||||
|
||||
/// \fn copy_if_until ( const Range& r, OutputIterator result, CopyPredicate copy_pred, TerminatePred term_pred )
|
||||
/// \brief Copies all the elements from the input range that satisfy the
|
||||
/// copy predicate to the output range until the termination predicate is
|
||||
/// satisfied.
|
||||
/// \return The updated output iterator
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param result An output iterator to write the results into
|
||||
/// \param copy_pred A predicate for testing whether to the current element
|
||||
/// \param term_pred A predicate for testing whether to end the copy operation
|
||||
template<typename Range, typename OutputIterator, typename CopyPredicate, typename TerminatePred>
|
||||
BOOST_CXX14_CONSTEXPR std::pair<typename boost::range_iterator<const Range>::type, OutputIterator>
|
||||
copy_if_until ( const Range& r, OutputIterator result, CopyPredicate copy_pred, TerminatePred term_pred)
|
||||
{
|
||||
return boost::algorithm::copy_if_until(boost::begin(r), boost::end(r), result, copy_pred, term_pred);
|
||||
}
|
||||
|
||||
}} // namespace boost and algorithm
|
||||
|
||||
#endif // BOOST_ALGORITHM_COPY_IF_HPP
|
||||
|
@ -34,13 +34,15 @@ BOOST_CXX14_CONSTEXPR bool is_even ( int v ) { return v % 2 == 0; }
|
||||
BOOST_CXX14_CONSTEXPR bool is_odd ( int v ) { return v % 2 == 1; }
|
||||
BOOST_CXX14_CONSTEXPR bool is_zero ( int v ) { return v == 0; }
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool less_than_ten ( int v ) { return v < 10; }
|
||||
BOOST_CXX14_CONSTEXPR bool greater_than_ten ( int v ) { return v > 10; }
|
||||
|
||||
template <typename Container>
|
||||
void test_copy_if ( Container const &c ) {
|
||||
|
||||
typedef typename Container::value_type value_type;
|
||||
std::vector<value_type> v;
|
||||
|
||||
|
||||
// None of the elements
|
||||
v.clear ();
|
||||
ba::copy_if ( c.begin (), c.end (), back_inserter ( v ), is_false);
|
||||
@ -118,6 +120,160 @@ void test_copy_while ( Container const &c ) {
|
||||
BOOST_CHECK ( std::equal ( v.begin (), v.end (), c.begin ()));
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
void test_copy_if_while ( Container const &c ) {
|
||||
|
||||
typedef typename Container::value_type value_type;
|
||||
typename Container::const_iterator it;
|
||||
|
||||
// Terminate immediately
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
ba::copy_if_while ( c.begin (), c.end (), back_inserter ( v ), is_true, is_false);
|
||||
BOOST_CHECK ( v.size () == 0 );
|
||||
}
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
ba::copy_if_while ( c, back_inserter ( v ), is_true, is_false);
|
||||
BOOST_CHECK ( v.size () == 0 );
|
||||
}
|
||||
|
||||
// Copy nothing - never terminate
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
ba::copy_if_while ( c.begin (), c.end (), back_inserter ( v ), is_false, is_true);
|
||||
BOOST_CHECK ( v.size () == 0 );
|
||||
}
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
ba::copy_if_while ( c, back_inserter ( v ), is_false, is_true);
|
||||
BOOST_CHECK ( v.size () == 0 );
|
||||
}
|
||||
|
||||
// Copy everything
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
ba::copy_if_while ( c.begin (), c.end (), back_inserter ( v ), is_true, is_true);
|
||||
BOOST_CHECK ( v.size () == c.size() );
|
||||
BOOST_CHECK ( std::equal ( v.begin (), v.end (), c.begin ()));
|
||||
}
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
ba::copy_if_while ( c, back_inserter ( v ), is_true, is_true);
|
||||
BOOST_CHECK ( v.size () == c.size() );
|
||||
BOOST_CHECK ( std::equal ( v.begin (), v.end (), c.begin ()));
|
||||
}
|
||||
|
||||
// Copy all evens
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
ba::copy_if_while ( c.begin (), c.end (), back_inserter ( v ), is_even, is_true);
|
||||
BOOST_CHECK ( v.size () == (size_t) std::count_if ( c.begin (), c.end (), is_even ));
|
||||
BOOST_CHECK ( ba::all_of ( v.begin (), v.end (), is_even ));
|
||||
}
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
ba::copy_if_while ( c, back_inserter ( v ), is_even, is_true);
|
||||
BOOST_CHECK ( v.size () == (size_t) std::count_if ( c.begin (), c.end (), is_even ));
|
||||
BOOST_CHECK ( ba::all_of ( v.begin (), v.end (), is_even ));
|
||||
}
|
||||
|
||||
// Copy some until termination
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
typename Container::const_iterator it = ba::copy_if_while (
|
||||
c.begin (), c.end (), back_inserter ( v ), is_even, less_than_ten).first;
|
||||
BOOST_CHECK ( it == std::find_if ( c.begin(), c.end(), greater_than_ten ));
|
||||
BOOST_CHECK ( v.size () == std::count_if ( c.begin(), it, is_even ));
|
||||
BOOST_CHECK ( ba::all_of ( v.begin (), v.end (), is_even ));
|
||||
}
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
typename Container::const_iterator it = ba::copy_if_while (
|
||||
c, back_inserter ( v ), is_even, less_than_ten).first;
|
||||
BOOST_CHECK ( it == std::find_if ( c.begin(), c.end(), greater_than_ten ));
|
||||
BOOST_CHECK ( v.size () == std::count_if ( c.begin(), it, is_even ));
|
||||
BOOST_CHECK ( ba::all_of ( v.begin (), v.end (), is_even ));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
void test_copy_if_until ( Container const &c ) {
|
||||
|
||||
typedef typename Container::value_type value_type;
|
||||
typename Container::const_iterator it;
|
||||
|
||||
// Terminate immediately
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
ba::copy_if_until ( c.begin (), c.end (), back_inserter ( v ), is_true, is_true);
|
||||
BOOST_CHECK ( v.size () == 0 );
|
||||
}
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
ba::copy_if_until ( c, back_inserter ( v ), is_true, is_true);
|
||||
BOOST_CHECK ( v.size () == 0 );
|
||||
}
|
||||
|
||||
// Copy nothing - never terminate
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
ba::copy_if_until ( c.begin (), c.end (), back_inserter ( v ), is_false, is_false);
|
||||
BOOST_CHECK ( v.size () == 0 );
|
||||
}
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
ba::copy_if_until ( c, back_inserter ( v ), is_false, is_false);
|
||||
BOOST_CHECK ( v.size () == 0 );
|
||||
}
|
||||
|
||||
// Copy everything
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
ba::copy_if_until ( c.begin (), c.end (), back_inserter ( v ), is_true, is_false);
|
||||
BOOST_CHECK ( v.size () == c.size() );
|
||||
BOOST_CHECK ( std::equal ( v.begin (), v.end (), c.begin ()));
|
||||
}
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
ba::copy_if_until ( c, back_inserter ( v ), is_true, is_false);
|
||||
BOOST_CHECK ( v.size () == c.size() );
|
||||
BOOST_CHECK ( std::equal ( v.begin (), v.end (), c.begin ()));
|
||||
}
|
||||
|
||||
// Copy all evens
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
ba::copy_if_until ( c.begin (), c.end (), back_inserter ( v ), is_even, is_false);
|
||||
BOOST_CHECK ( v.size () == (size_t) std::count_if ( c.begin (), c.end (), is_even ));
|
||||
BOOST_CHECK ( ba::all_of ( v.begin (), v.end (), is_even ));
|
||||
}
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
ba::copy_if_until ( c, back_inserter ( v ), is_even, is_false);
|
||||
BOOST_CHECK ( v.size () == (size_t) std::count_if ( c.begin (), c.end (), is_even ));
|
||||
BOOST_CHECK ( ba::all_of ( v.begin (), v.end (), is_even ));
|
||||
}
|
||||
|
||||
// Copy some until termination
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
typename Container::const_iterator it = ba::copy_if_until (
|
||||
c.begin (), c.end (), back_inserter ( v ), is_even, greater_than_ten).first;
|
||||
BOOST_CHECK ( it == std::find_if ( c.begin(), c.end(), greater_than_ten ));
|
||||
BOOST_CHECK ( v.size () == std::count_if ( c.begin(), it, is_even ));
|
||||
BOOST_CHECK ( ba::all_of ( v.begin (), v.end (), is_even ));
|
||||
}
|
||||
{
|
||||
std::vector<value_type> v;
|
||||
typename Container::const_iterator it = ba::copy_if_until (
|
||||
c, back_inserter ( v ), is_even, greater_than_ten).first;
|
||||
BOOST_CHECK ( it == std::find_if ( c.begin(), c.end(), greater_than_ten ));
|
||||
BOOST_CHECK ( v.size () == std::count_if ( c.begin(), it, is_even ));
|
||||
BOOST_CHECK ( ba::all_of ( v.begin (), v.end (), is_even ));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
void test_copy_until ( Container const &c ) {
|
||||
|
||||
@ -224,8 +380,77 @@ BOOST_CXX14_CONSTEXPR inline bool constexpr_test_copy_until() {
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_CXX14_CONSTEXPR inline bool constexpr_test_copy_if_while() {
|
||||
const int sz = 64;
|
||||
int in_data[sz] = {0};
|
||||
bool res = true;
|
||||
|
||||
const int* from = in_data;
|
||||
const int* to = in_data + sz;
|
||||
|
||||
// Terminate immediately
|
||||
{
|
||||
int out_data[sz] = {0};
|
||||
int* out = out_data;
|
||||
out = ba::copy_if_while ( from, to, out, is_true, is_false ).second;
|
||||
res = (res && out == out_data && ba::all_of(out, out + sz, is_zero));
|
||||
}
|
||||
// Copy nothing
|
||||
{
|
||||
int out_data[sz] = {0};
|
||||
int* out = out_data;
|
||||
out = ba::copy_if_while ( from, to, out, is_false, is_true ).second;
|
||||
res = (res && out == out_data && ba::all_of(out, out + sz, is_zero));
|
||||
}
|
||||
// Copy everything
|
||||
{
|
||||
int out_data[sz] = {0};
|
||||
int* out = out_data;
|
||||
out = ba::copy_if_while ( from, to, out, is_true, is_true ).second;
|
||||
res = (res && out == out_data + sz
|
||||
&& ba::equal( input_iterator<const int *>(out_data), input_iterator<const int *>(out_data + sz),
|
||||
input_iterator<const int *>(from), input_iterator<const int *>(to)));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR inline bool constexpr_test_copy_if_until() {
|
||||
const int sz = 64;
|
||||
int in_data[sz] = {0};
|
||||
bool res = true;
|
||||
|
||||
const int* from = in_data;
|
||||
const int* to = in_data + sz;
|
||||
|
||||
// Terminate immediately
|
||||
{
|
||||
int out_data[sz] = {0};
|
||||
int* out = out_data;
|
||||
out = ba::copy_if_until ( from, to, out, is_true, is_true ).second;
|
||||
res = (res && out == out_data && ba::all_of(out, out + sz, is_zero));
|
||||
}
|
||||
// Copy nothing
|
||||
{
|
||||
int out_data[sz] = {0};
|
||||
int* out = out_data;
|
||||
out = ba::copy_if_until ( from, to, out, is_false, is_false ).second;
|
||||
res = (res && out == out_data && ba::all_of(out, out + sz, is_zero));
|
||||
}
|
||||
// Copy everything
|
||||
{
|
||||
int out_data[sz] = {0};
|
||||
int* out = out_data;
|
||||
out = ba::copy_if_until ( from, to, out, is_true, is_false ).second;
|
||||
res = (res && out == out_data + sz
|
||||
&& ba::equal( input_iterator<const int *>(out_data), input_iterator<const int *>(out_data + sz),
|
||||
input_iterator<const int *>(from), input_iterator<const int *>(to)));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void test_sequence1 () {
|
||||
std::vector<int> v;
|
||||
for ( int i = 5; i < 15; ++i )
|
||||
@ -233,20 +458,26 @@ void test_sequence1 () {
|
||||
test_copy_if ( v );
|
||||
test_copy_while ( v );
|
||||
test_copy_until ( v );
|
||||
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool constexpr_res_if = constexpr_test_copy_if();
|
||||
BOOST_CHECK ( constexpr_res_if );
|
||||
BOOST_CXX14_CONSTEXPR bool constexpr_res_while = constexpr_test_copy_while();
|
||||
BOOST_CHECK ( constexpr_res_while );
|
||||
BOOST_CXX14_CONSTEXPR bool constexpr_res_until = constexpr_test_copy_until();
|
||||
BOOST_CHECK ( constexpr_res_until );
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool constexpr_res_if_while = constexpr_test_copy_if_while();
|
||||
BOOST_CHECK ( constexpr_res_if_while );
|
||||
BOOST_CXX14_CONSTEXPR bool constexpr_res_if_until = constexpr_test_copy_if_until();
|
||||
BOOST_CHECK ( constexpr_res_if_until );
|
||||
|
||||
std::list<int> l;
|
||||
for ( int i = 25; i > 15; --i )
|
||||
l.push_back ( i );
|
||||
test_copy_if ( l );
|
||||
test_copy_while ( l );
|
||||
test_copy_until ( l );
|
||||
test_copy_if_while ( l );
|
||||
test_copy_if_until ( l );
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user