C++/STL Basics/predicate
Содержание
- 1 Convenience function for the compose_f_gx adapter
- 2 Convenience function for the compose_f_gx_hx adapter
- 3 Convenience function for the compose_f_gx_hy adapter
- 4 Create your own unary function
- 5 Function object to process the mean value
- 6 Illustrating the use of an adaptor for pointers to functions
- 7 use generic function as predicate
- 8 Use predicate, which returns whether an integer is a prime number, with a list
Convenience function for the compose_f_gx adapter
/* The following code example is taken from the book
* "The C++ Standard Library - A Tutorial and Reference"
* by Nicolai M. Josuttis, Addison-Wesley, 1999
*
* (C) Copyright Nicolai M. Josuttis 1999.
* Permission to copy, use, modify, sell and distribute this software
* is granted provided this copyright notice appears in all copies.
* This software is provided "as is" without express or implied
* warranty, and with no claim as to its suitability for any purpose.
*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <iterator>
using namespace std;
/* PRINT_ELEMENTS()
* - prints optional C-string optcstr followed by
* - all elements of the collection coll
* - separated by spaces
*/
template <class T>
inline void PRINT_ELEMENTS (const T& coll, const char* optcstr="")
{
typename T::const_iterator pos;
std::cout << optcstr;
for (pos=coll.begin(); pos!=coll.end(); ++pos) {
std::cout << *pos << " ";
}
std::cout << std::endl;
}
/* class for the compose_f_gx adapter
*/
template <class OP1, class OP2>
class compose_f_gx_t
: public std::unary_function<typename OP2::argument_type,
typename OP1::result_type>
{
private:
OP1 op1; // process: op1(op2(x))
OP2 op2;
public:
// constructor
compose_f_gx_t(const OP1& o1, const OP2& o2)
: op1(o1), op2(o2) {
}
// function call
typename OP1::result_type
operator()(const typename OP2::argument_type& x) const {
return op1(op2(x));
}
};
/* convenience function for the compose_f_gx adapter
*/
template <class OP1, class OP2>
inline compose_f_gx_t<OP1,OP2>
compose_f_gx (const OP1& o1, const OP2& o2) {
return compose_f_gx_t<OP1,OP2>(o1,o2);
}
int main()
{
vector<int> coll;
// insert elements from 1 to 9
for (int i=1; i<=9; ++i) {
coll.push_back(i);
}
PRINT_ELEMENTS(coll);
// for each element add 10 and multiply by 5
transform (coll.begin(),coll.end(),
ostream_iterator<int>(cout," "),
compose_f_gx(bind2nd(multiplies<int>(),5),
bind2nd(plus<int>(),10)));
cout << endl;
}
/*
1 2 3 4 5 6 7 8 9
55 60 65 70 75 80 85 90 95
*/
Convenience function for the compose_f_gx_hx adapter
/* The following code example is taken from the book
* "The C++ Standard Library - A Tutorial and Reference"
* by Nicolai M. Josuttis, Addison-Wesley, 1999
*
* (C) Copyright Nicolai M. Josuttis 1999.
* Permission to copy, use, modify, sell and distribute this software
* is granted provided this copyright notice appears in all copies.
* This software is provided "as is" without express or implied
* warranty, and with no claim as to its suitability for any purpose.
*/
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#include <functional>
#include <iostream>
/* PRINT_ELEMENTS()
* - prints optional C-string optcstr followed by
* - all elements of the collection coll
* - separated by spaces
*/
template <class T>
inline void PRINT_ELEMENTS (const T& coll, const char* optcstr="")
{
typename T::const_iterator pos;
std::cout << optcstr;
for (pos=coll.begin(); pos!=coll.end(); ++pos) {
std::cout << *pos << " ";
}
std::cout << std::endl;
}
/* class for the compose_f_gx_hx adapter
*/
template <class OP1, class OP2, class OP3>
class compose_f_gx_hx_t
: public std::unary_function<typename OP2::argument_type,
typename OP1::result_type>
{
private:
OP1 op1; // process: op1(op2(x),op3(x))
OP2 op2;
OP3 op3;
public:
// constructor
compose_f_gx_hx_t (const OP1& o1, const OP2& o2, const OP3& o3)
: op1(o1), op2(o2), op3(o3) {
}
// function call
typename OP1::result_type
operator()(const typename OP2::argument_type& x) const {
return op1(op2(x),op3(x));
}
};
/* convenience function for the compose_f_gx_hx adapter
*/
template <class OP1, class OP2, class OP3>
inline compose_f_gx_hx_t<OP1,OP2,OP3>
compose_f_gx_hx (const OP1& o1, const OP2& o2, const OP3& o3) {
return compose_f_gx_hx_t<OP1,OP2,OP3>(o1,o2,o3);
}
int main()
{
vector<int> coll;
// insert elements from 1 to 9
for (int i=1; i<=9; ++i) {
coll.push_back(i);
}
PRINT_ELEMENTS(coll);
// remove all elements that are greater than four and less than seven
// - retain new end
vector<int>::iterator pos;
pos = remove_if (coll.begin(),coll.end(),
compose_f_gx_hx(logical_and<bool>(),
bind2nd(greater<int>(),4),
bind2nd(less<int>(),7)));
// remove ""removed"" elements in coll
coll.erase(pos,coll.end());
PRINT_ELEMENTS(coll);
}
/*
1 2 3 4 5 6 7 8 9
1 2 3 4 7 8 9
*/
Convenience function for the compose_f_gx_hy adapter
/* The following code example is taken from the book
* "The C++ Standard Library - A Tutorial and Reference"
* by Nicolai M. Josuttis, Addison-Wesley, 1999
*
* (C) Copyright Nicolai M. Josuttis 1999.
* Permission to copy, use, modify, sell and distribute this software
* is granted provided this copyright notice appears in all copies.
* This software is provided "as is" without express or implied
* warranty, and with no claim as to its suitability for any purpose.
*/
#include <iostream>
#include <algorithm>
#include <functional>
#include <string>
#include <cctype>
using namespace std;
#include <functional>
/* class for the compose_f_gx_hy adapter
*/
template <class OP1, class OP2, class OP3>
class compose_f_gx_hy_t
: public std::binary_function<typename OP2::argument_type,
typename OP3::argument_type,
typename OP1::result_type>
{
private:
OP1 op1; // process: op1(op2(x),op3(y))
OP2 op2;
OP3 op3;
public:
// constructor
compose_f_gx_hy_t (const OP1& o1, const OP2& o2, const OP3& o3)
: op1(o1), op2(o2), op3(o3) {
}
// function call
typename OP1::result_type
operator()(const typename OP2::argument_type& x,
const typename OP3::argument_type& y) const {
return op1(op2(x),op3(y));
}
};
/* convenience function for the compose_f_gx_hy adapter
*/
template <class OP1, class OP2, class OP3>
inline compose_f_gx_hy_t<OP1,OP2,OP3>
compose_f_gx_hy (const OP1& o1, const OP2& o2, const OP3& o3) {
return compose_f_gx_hy_t<OP1,OP2,OP3>(o1,o2,o3);
}
int main()
{
string s("Internationalization");
string sub("Nation");
// search substring case insensitive
string::iterator pos;
pos = search (s.begin(),s.end(), // string to search in
sub.begin(),sub.end(), // substring to search
compose_f_gx_hy(equal_to<int>(), // compar. criterion
ptr_fun(::toupper),
ptr_fun(::toupper)));
if (pos != s.end()) {
cout << "\"" << sub << "\" is part of \"" << s << "\""
<< endl;
}
}
/*
"Nation" is part of "Internationalization"
*/
Create your own unary function
#include <iostream>
#include <list>
#include <functional>
#include <algorithm>
using namespace std;
class reciprocal: unary_function<double, double> {
public:
result_type operator()(argument_type i)
{
return (result_type) 1.0/i;
}
};
int main()
{
list<double> vals;
for(int i=1; i<10; i++) vals.push_back((double)i);
cout << "Original contents of vals:\n";
list<double>::iterator p = vals.begin();
while(p != vals.end()) {
cout << *p << " ";
p++;
}
cout << endl;
// use reciprocal function object
p = transform(vals.begin(), vals.end(),
vals.begin(),
reciprocal()); // call function object
cout << "Transformed contents of vals:\n";
p = vals.begin();
while(p != vals.end()) {
cout << *p << " ";
p++;
}
return 0;
}
/*
Original contents of vals:
1 2 3 4 5 6 7 8 9
Transformed contents of vals:
1 0.5 0.333333 0.25 0.2 0.166667 0.142857 0.125 0.111111
*/
Function object to process the mean value
/* The following code example is taken from the book
* "The C++ Standard Library - A Tutorial and Reference"
* by Nicolai M. Josuttis, Addison-Wesley, 1999
*
* (C) Copyright Nicolai M. Josuttis 1999.
* Permission to copy, use, modify, sell and distribute this software
* is granted provided this copyright notice appears in all copies.
* This software is provided "as is" without express or implied
* warranty, and with no claim as to its suitability for any purpose.
*/
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// function object to process the mean value
class MeanValue {
private:
long num; // number of elements
long sum; // sum of all element values
public:
// constructor
MeanValue () : num(0), sum(0) {
}
// ""function call""
// - process one more element of the sequence
void operator() (int elem) {
num++; // increment count
sum += elem; // add value
}
// return mean value
double value () {
return static_cast<double>(sum) / static_cast<double>(num);
}
};
int main()
{
vector<int> coll;
// insert elments from 1 to 8
for (int i=1; i<=8; ++i) {
coll.push_back(i);
}
// process and print mean value
MeanValue mv = for_each (coll.begin(), coll.end(), // range
MeanValue()); // operation
cout << "mean value: " << mv.value() << endl;
}
/*
mean value: 4.5
*/
Illustrating the use of an adaptor for pointers to functions
//Revised from
//STL Tutorial and Reference Guide C++ Programming with the Standard Template Library, 2nd Edition
//by David R. Musser (Author), Atul Saini (Author)
//# Publisher: Addison-Wesley Pub (Sd) (March 1996)
//# Language: English
//# ISBN-10: 0201633981
//# ISBN-13: 978-0201633986
#include <iostream>
#include <string>
#include <set>
using namespace std;
bool less1(const string& x, const string& y)
{
return x < y;
}
bool greater1(const string& x, const string& y)
{
return x > y;
}
int main()
{
typedef set<string, pointer_to_binary_function<const string&, const string&,bool> > set_type1;
set_type1 set1(ptr_fun(less1));
set1.insert("the");
set1.insert("quick");
set1.insert("brown");
set1.insert("fox");
set_type1::iterator i;
for (i = set1.begin(); i != set1.end(); ++i)
cout << *i << " ";
cout << endl;
set_type1 set2(ptr_fun(greater1));
set2.insert("the");
set2.insert("quick");
set2.insert("brown");
set2.insert("fox");
for (i = set2.begin(); i != set2.end(); ++i)
cout << *i << " ";
cout << endl;
return 0;
}
/*
brown fox quick the
the quick fox brown
*/
use generic function as predicate
/* The following code example is taken from the book
* "C++ Templates - The Complete Guide"
* by David Vandevoorde and Nicolai M. Josuttis, Addison-Wesley, 2002
*
* (C) Copyright David Vandevoorde and Nicolai M. Josuttis 2002.
* Permission to copy, use, modify, sell and distribute this software
* is granted provided this copyright notice appears in all copies.
* This software is provided "as is" without express or implied
* warranty, and with no claim as to its suitability for any purpose.
*/
#include <iostream>
using namespace std;
template <typename T, int VAL>
T addValue (T const& x)
{
return x + VAL;
}
void call_addValue()
{
addValue<int,5>(42);
}
template <typename IT, typename OP>
void transform (IT beg, IT end, IT to, OP op)
{
while (beg != end) {
*to++ = op(*beg++);
}
}
int main()
{
call_addValue();
int m[] = { 1, 2, 3, 4, 5, 6 };
transform (m, m+6,
m,
(int(*)(int const&)) // cast necessary
addValue<int,5>);
for(int i=0;i<6;i++){
cout << m[i] << " ";
}
}
/*
6 7 8 9 10 11
*/
Use predicate, which returns whether an integer is a prime number, with a list
/* The following code example is taken from the book
* "The C++ Standard Library - A Tutorial and Reference"
* by Nicolai M. Josuttis, Addison-Wesley, 1999
*
* (C) Copyright Nicolai M. Josuttis 1999.
* Permission to copy, use, modify, sell and distribute this software
* is granted provided this copyright notice appears in all copies.
* This software is provided "as is" without express or implied
* warranty, and with no claim as to its suitability for any purpose.
*/
#include <iostream>
#include <list>
#include <algorithm>
#include <cstdlib> // for abs()
using namespace std;
// predicate, which returns whether an integer is a prime number
bool isPrime (int number)
{
// ignore negative sign
number = abs(number);
// 0 and 1 are no prime numbers
if (number == 0 || number == 1) {
return false;
}
// find divisor that divides without a remainder
int divisor;
for (divisor = number/2; numberdivisor != 0; --divisor) {
;
}
// if no divisor greater than 1 is found, it is a prime number
return divisor == 1;
}
int main()
{
list<int> coll;
// insert elements from 24 to 30
for (int i=24; i<=30; ++i) {
coll.push_back(i);
}
// search for prime number
list<int>::iterator pos;
pos = find_if (coll.begin(), coll.end(), // range
isPrime); // predicate
if (pos != coll.end()) {
// found
cout << *pos << " is first prime number found" << endl;
}
else {
// not found
cout << "no prime number found" << endl;
}
}
/*
29 is first prime number found
*/