注:博客内容均来自于对《C++标准库》侯捷,华中科技大学出版社一书的笔记。转载请注明出处。
所有例程在Red Hat Linux 3.2.2-5版本上编译运行,g++的版本是 g++ (GCC) 3.2.2 20030222。
这个其实是前面已经举过的例子,利用自定义排序规则对容器类元素进行排序。
#include <iostream> #include <string> #include <set> #include <algorithm> using namespace std; class Person { public: Person(string a,string b) : strFirstname(a),strLastname(b) {} public: string firstname() const { return strFirstname; } string lastname() const { return strLastname; } private: const string strFirstname; const string strLastname; }; //仿函数实现自定义排序 class PersonSortCriterion { public : //仿函数 //排序规则为:按照lastname升序排列,lastname相同时按firstname升序排列 bool operator()(const Person &p1, const Person &p2) { return (p1.lastname() < p2.lastname() || (!(p2.lastname() < p1.lastname()) && p1.firstname() < p2.firstname())); } }; int main(int argc, char *argv[]) { //类型重定义,并指定排序规则 typedef set<Person, PersonSortCriterion> PersonSet; PersonSet col1; //创建元素,并添加到容器 Person p1("Jay", "Chou"); Person p2("Robin", "Chou"); Person p3("Robin", "Lee"); Person p4("Bob", "Smith"); //向容器中插入元素 col1.insert(p1); col1.insert(p2); col1.insert(p3); col1.insert(p4); PersonSet::iterator pos; //输出PersonSet中的所有元素 for(pos = col1.begin(); pos != col1.end(); ++pos) { cout<<pos->firstname()<< " " << pos->lastname() << endl; } cout<<endl; return 0; }
#include <iostream> #icnlude <list> #icnlude <algorithm> #icnlude "print.h" using namespace std; class IntSequence { private: int value; //记录内部状态的成员变量 public: IntSequence (int initialValue) : value(initialValue) { } //仿函数 int operator()() { return value++; } }; int main() { list<int> col1; //产生长度为9的序列,依次插值到col1容器的尾部 generate_n(back_inserter(col1), 9, IntSequence(1)); //1 2 3 4 5 6 7 8 9 PRINT_ELEMENTS(col1); //替换col1容器中第2个到倒数第2个,从42开始 generate(++col1.begin(), --col1.end(), IntSequence(42)); //1 42 43 44 45 46 47 48 9 PRINT_ELEMENTS(col1); return 0; }
特别注意:
仿函数都是传值,而不是传址的。因此算法并不会改变随参数而来的仿函数的状态。
比如:因为for_each()算法它返回其仿函数。也就是说,我们可以通过返回值可以取得仿函数的状态。
下面来分别举例说明:
#include <iostream> #include <list> #include <algorithm> #include "print.h" using namespace std; class IntSequence { private: int value; public: IntSequence(int initValue) : value(initValue) {} int operator()() { return value++; } }; int main() { list<int> col1; IntSequence seq(1); //采用引用类型 generate_n<back_insert_iterator<list<int> >, int, IntSequence&>(back_inserter(col1), 4, seq); //1 2 3 4; PRINT_ELEMENTS(col1); //相当于重新构建一个对象从42开始插入4个元素 generate_n(back_inserter(col1), 4, IntSequence(42)); //1 2 3 4; 42 43 44 45 PRINT_ELEMENTS(col1); //前面使用的是引用类型,所以seq的内部状态已经被改变了 //插值从上次完成后的5开始 //注意:这次调用仍然使用的是传值类型 generate_n(back_inserter(col1), 4, seq); //1 2 3 4; 42 43 44 45; 5 6 7 8 PRINT_ELEMENTS(col1); //上一次调用使用的是传值类型,所以这次还是从5开始插值 generate_n(back_inserter(col1), 4, seq); //1 2 3 4; 42 43 44 45; 5 6 7 8; 5 6 7 8 PRINT_ELEMENTS(col1); return 0; }
#include <iostream> #include <vector> #include <algorithm> using namespace std; class MeanValue { private: long num; long sum; public: MeanValue(): num(0), sum(0) {} void operator() (int elem) { num++; sum += elem; } double value() { return static_cast<double>(sum) / static_cast<double>(num); } }; int main() { vector<int> col1; for(int i=1; i<=8; ++i) { col1.push_back(i); } MeanValue mv = for_each(col1.begin(), col1.end(), MeanValue()); cout<< "Mean Value: " << mv.value() << endl return 0; }
#include <iostream> #include <list> #include <algorithm> #include "print.h" using namespace std; class Nth { private: int nth; int count; public: Nth(int n): nth(n), count(0) { } bool operator() (int) { return ++count == nth; } }; int main() { list<int> col1; for(int i=1; i<=9; ++i) { col1.push_back(i); } //1 2 3 4 5 6 7 8 9 PRINT_ELEMENTS(col1); list<int>::iterator pos; pos = remove_if(col1.begin(), col1.end(), Nth(3)); col1.erase(pos,col1.end()); PRINT_ELEMENTS(col1); }
举例如下:
#include <iostream> #include <string> #include <vector> #include <functional> using namespace std; //针对成员函数设计的函数配接器 class Person { private: string name; public: Person(){} Person(string str): name(str) {} //输出name void print() const { cout << name << endl; } //输出name 和 prefix void PrintWithPrefix(string prefix) const { cout << prefix << name << endl; } }; void foo(const vector<Person>& col1) { //对容器中的每一个元素执行仿函数mem_fun_ref(&Person::print) for_each(col1.begin(), col1.end(), mem_fun_ref(&Person::print)); //对容器中的每一个元素执行仿函数bind2nd(mem_fun_ref(&Person::PrintWithPrefix) for_each(colq.begin(), col1.end(), bind2nd(mem_fun_ref(&Person::PrintWithPrefix),"Person: ")); } int main() { vector<Person> col1; Person p1("Robin"); Person p2("Romio"); col1.push_back(p1); col2.push_back(p2); foo(col1); return 0; }
举例如下:
#include <iostream> #include <vector> #include <functional> using namespace std; //针对一般函数设计的函数配接器 bool isThree(int em) { if(em == 3) { cout<< em << "is 3" <<endl; return true; } else { cout<< em << "is not 3"<<endl; return false; } } bool isElement(int em, int rem) { if(em == rem) { cout<< em << "is "<< rem << endl; } else { cout<< em << "is not "<< rem << endl; } } int main() { vector<int> col1; for(int i=0;i<9;++i) { col1.push_back(i); } for_each(col1.begin(), col1.end(), not1(ptr_fun(isThree))); //将一般函数isThree转换成仿函数 cout<<endl; for_each(col1.begin(), col1.end(), bind2nd(ptr_fun(isElement),5)); return 0; }
#ifndef __FOPOW_H #define __FOPOW_H #include <functional> #include <cmath> template <class T1, class T2> struct fopow : public std::binary_function<T1, T2, T1> { T1 operator() (T1 base, T2 exp) const { return std::pow(base, exp); } }; #endif //__FOPOW_H
#include <iostream> #include <vector> #include <algorithm> #include <iterator> #include "fopow.h" using namespace std; int main() { vector<int> col1; for(int i=1; i<=9; ++i) { col1.push_back(i); } transform(col1.begin(), col1.end(), ostream_iterator<int>(cout, " "), bind1st(fopow<float,int>(), 3)); cout<<endl; transform(col1.begin(), col1.end(), ostream_iterator<int>(cout, " "), bind2nd(fopow<float,int>(), 3)); cout<<endl; return 0; }
#ifndef __COMPOSE_H #define __COMPOSE_H #include <functional> 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; OP2 op2; public: compose_f_gx_t(const OP1& o1, const OP2& o2) : op1(o1), op2(o2) {} typename OP1::result_type operator() (const typename OP2::argument_type& x) const { return op1(op2(x)); } }; 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); } #endif //__COMPOSE_H
#include <iostream> #include <vector> #include <algorithm> #include <functional> #include <iterator> #include "print.h" #include "compose11.h" using namespace std; int main() { vector<int> col1; for(int i=1; i<=9; ++i) { col1.push_back(i); } PRINT_ELEMENTS(col1); transform(col1.begin(), col1.end(), ostream_iterator<int>(cout, " "), compose_f_gx(bind2nd(multiplies<int>(),5), bind2nd(plus<int>(),10))); cout<<endl; }
#ifndef __COMPOSE_H #define __COMPOSE_H #include <functional> 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; OP2 op2; OP3 op3; public: compose_f_gx_hx_t(const OP1& o1, const OP2& o2,const OP3& o3) : op1(o1), op2(o2), op3(o3) {} typename OP1::result_type operator() (const typename OP2::argument_type& x) const { return op1(op2(x), op3(x)); } }; 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); } #endif //__COMPOSE_H
#include <iostream> #include <vector> #include <algorithm> #include <functional> #include <iterator> #include "print.h" #include "compose21.h" using namespace std; int main() { vector<int> col1; for(int i=1; i<=9; ++i) { col1.push_back(i); } PRINT_ELEMENTS(col1); vector<int>::iterator pos; pos = remove_if(col1.begin(), col1.end(), compose_f_gx_hx(logical_and<bool>(), bind2nd(greater<int>(), 4), bind2nd(less<int>(), 7))); col1.erase(pos, col1.end()); PRINT_ELEMENTS(col1); cout<<endl; return 0; }
#ifndef __COMPOSE_H #define __COMPOSE_H #include <functional> 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; //op1(op2(x),op3(y)) OP2 op2; OP3 op3; public: compose_f_gx_hy_t(const OP1& o1, const OP2& o2, const OP3& o3) : op1(o1), op2(o2), op3(o3) { } typename OP1::result_type operator()(const typename OP2::argument_type& x, const typename OP3::argument_type& y) const { return op1(op2(x), op3(y)); } }; 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); } #endif //__COMPOSE_H
#include <cctype> #include <iostream> #include <algorithm> #include <functional> #include <string> #include "compose22.h" using namespace std; int main() { string s("Internationalization"); string sub("Nation"); string::iterator pos; pos = search(s.begin(), s.end(), sub.begin(), sub.end(), compose_f_gx_hy(equal_to<int>(), ptr_fun(::toupper), ptr_fun(::toupper))); if(pos != s.end()) { cout<< "\"" << sub << "\" is a part of \"" << s << "\"" << endl; } //int sum = compose_f_gx_hy(plus<int>(),20,30); return 0; }