Thinking in C++ Vol 2 - Practical Programming |
Prev |
Home |
Next |
At times, you might want to copy only a well-defined subset
of one sequence to another, such as only those elements that satisfy a particular
condition. To achieve this flexibility, many algorithms have alternate calling
sequences that allow you to supply a predicate, which is simply a function that returns a Boolean value based on some criterion. Suppose, for example, that you
only want to extract from a sequence of integers those numbers that are less
than or equal to 15. A version of copy( ) called remove_copy_if( ) can do the job, like this:
//: C06:CopyInts2.cpp
// Ignores ints that satisfy a predicate.
#include <algorithm>
#include <cstddef>
#include <iostream>
using namespace std;
// You supply this predicate
bool gt15(int x) { return 15 < x; }
int main() {
int a[] = { 10, 20, 30 };
const size_t SIZE = sizeof a / sizeof a[0];
int b[SIZE];
int* endb = remove_copy_if(a, a+SIZE, b, gt15);
int* beginb = b;
while(beginb != endb)
cout << *beginb++ << endl; // Prints 10
only
} ///:~
The remove_copy_if( ) function template takes
the usual range-delimiting pointers, followed by a predicate of your choosing.
The predicate must be a pointer to a function that
takes a single argument of the same type as the elements in the sequence, and
it must return a bool. Here, the function gt15 returns true
if its argument is greater than 15. The remove_copy_if( ) algorithm
applies gt15( ) to each element in the input sequence and ignores
those elements where the predicate yields true when writing to the output
sequence.
The following program illustrates yet another variation of
the copy algorithm:
//: C06:CopyStrings2.cpp
// Replaces strings that satisfy a predicate.
#include <algorithm>
#include <cstddef>
#include <iostream>
#include <string>
using namespace std;
// The predicate
bool contains_e(const string& s) {
return s.find('e') != string::npos;
}
int main() {
string a[] = {"read", "my",
"lips"};
const size_t SIZE = sizeof a / sizeof a[0];
string b[SIZE];
string* endb = replace_copy_if(a, a + SIZE, b,
contains_e, string("kiss"));
string* beginb = b;
while(beginb != endb)
cout << *beginb++ << endl;
} ///:~
Instead of just ignoring elements that don t satisfy the
predicate, replace_copy_if( ) substitutes a fixed value for such elements when populating the output sequence. The output is:
because the original occurrence of read, the only input
string containing the letter e, is replaced by the word kiss, as
specified in the last argument in the call to replace_copy_if( ).
The replace_if( ) algorithm changes the original sequence in place, instead of writing to a separate output sequence, as the
following program shows:
//: C06:ReplaceStrings.cpp
// Replaces strings in-place.
#include <algorithm>
#include <cstddef>
#include <iostream>
#include <string>
using namespace std;
bool contains_e(const string& s) {
return s.find('e') != string::npos;
}
int main() {
string a[] = {"read", "my",
"lips"};
const size_t SIZE = sizeof a / sizeof a[0];
replace_if(a, a + SIZE, contains_e,
string("kiss"));
string* p = a;
while(p != a + SIZE)
cout << *p++ << endl;
} ///:~
Thinking in C++ Vol 2 - Practical Programming |
Prev |
Home |
Next |