header < functional >
函数对象 利用操作符()的重载,使对象实现类似函数的功能,通常被用来做其他函数的谓词或者比较函数参数
1.基类
1.unary_function 一元函数模板
template <class Arg, class Result>
struct unary_function {
typedef Arg argument_type;
typedef Result result_type;
};
一元函数模板中的Arg代表operator()函数的唯一的参数的类型,Result代表operator()函数的返回值的类型。
// unary_function example
#include <iostream> // std::cout, std::cin
#include <functional> // std::unary_function
struct IsOdd : public std::unary_function<int,bool> {
bool operator() (int number) {return (number%2!=0);}
};
int main () {
IsOdd IsOdd_object;
IsOdd::argument_type input;
IsOdd::result_type result;
std::cout << "Please enter a number: ";
std::cin >> input;
result = IsOdd_object (input);
std::cout << "Number " << input << " is " << (result?"odd":"even") << ".\n";
return 0;
}
output:
Please enter a number: 2
Number 2 is even.
2.binary_function
template <class Arg1, class Arg2, class Result>
struct binary_function {
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};
类似unary_function的用法
2.操作符模板类
1.算数操纵符
**plus:**
template <class T> struct plus : binary_function <T,T,T>
{
T operator() (const T& x, const T& y) const {return x+y;}
};
//适用于transform和accumulate算法的参数
**minus:**
template <class T> struct minus : binary_function <T,T,T> {
T operator() (const T& x, const T& y) const {return x-y;}
};
//mutiplies,divide,modulus(相当于取余运算),negate(取一个数的相反数x->(-x))
2.关系操作符
equal_to:
template <class T> struct equal_to : binary_function <T,T,bool> {
bool operator() (const T& x, const T& y) const {return x==y;}
};
not_equal_to:
template <class T> struct not_equal_to : binary_function <T,T,bool> {
bool operator() (const T& x, const T& y) const {return x!=y;}
};
类似的还有greater,less,greater_equal,less_equal
3.逻辑操作符
logical_and:
template <class T>struct logical_and : binary_function <T,T,bool>
{
bool operator() (const T& x, const T& y) const {return x&&y;}
};
loical_or:
template <class T> struct logical_or : binary_function <T,T,bool> {
bool operator() (const T& x, const T& y) const {return x||y;}
};
logical_not:
template <class T> struct logical_not : unary_function <T,bool> {
bool operator() (const T& x) const {return !x;}
};
3.适配和转换函数
1.not1
template <class Predicate> unary_negate<Predicate> not1 (const Predicate& pred)
{
return unary_negate<Predicate>(pred);
}
// not1 example
#include <iostream> // std::cout
#include <functional> // std::not1
#include <algorithm> // std::count_if
struct IsOdd {
bool operator() (const int& x) const {return x%2==1;}
typedef int argument_type;
};
int main () {
int values[] = {1,2,3,4,5};
int cx = std::count_if (values, values+5, std::not1(IsOdd()));
std::cout << "There are " << cx << " elements with even values.\n";
return 0;
}
Output:
There are 2 elements with even values.
2.not2
template <class Predicate> binary_negate<Predicate> not2 (const Predicate& pred)
{
return binary_negate<Predicate>(pred);
}
// not2 example
#include <iostream> // std::cout
#include <functional> // std::not2, std::equal_to
#include <algorithm> // std::mismatch
#include <utility> // std::pair
int main () {
int foo[] = {10,20,30,40,50};
int bar[] = {0,15,30,45,60};
std::pair<int*,int*> firstmatch,firstmismatch;
firstmismatch = std::mismatch (foo, foo+5, bar, std::equal_to<int>());
firstmatch = std::mismatch (foo, foo+5, bar, std::not2(std::equal_to<int>()));
std::cout << "First mismatch in bar is " << *firstmismatch.second << '\n';
std::cout << "First match in bar is " << *firstmatch.second << '\n';
return 0;
}
First mismatch in bar is 0
First match in bar is 30
3.bind1st
template <class Operation, class T>
binder1st<Operation> bind1st (const Operation& op, const T& x);
// bind1st example
#include <iostream>
#include <functional>
#include <algorithm>
using namespace std;
int main () {
int numbers[] = {10,20,30,40,50,10};
int cx;
cx = count_if (numbers, numbers+6, bind1st(equal_to<int>(),10) );
cout << "There are " << cx << " elements that are equal to 10.\n";
return 0;
}
There are 2 elements that are equal to 10.
4.bind2nd
template <class Operation, class T>
binder2nd<Operation> bind2nd (const Operation& op, const T& x);
// bind2nd example
#include <iostream>
#include <functional>
#include <algorithm>
using namespace std;
int main () {
int numbers[] = {10,-20,-30,40,-50};
int cx;
cx = count_if ( numbers, numbers+5, bind2nd(less<int>(),0) );
cout << "There are " << cx << " negative elements.\n";
return 0;
}
There are 3 negative elements.
5.ptr_fun
template <class Arg, class Result>
pointer_to_unary_function<Arg,Result> ptr_fun (Result (*f)(Arg));
template <class Arg1, class Arg2, class Result>
pointer_to_binary_function<Arg1,Arg2,Result> ptr_fun (Result (*f)(Arg1,Arg2));
// ptr_fun example
#include <iostream>
#include <functional>
#include <algorithm>
#include <cstdlib>
#include <numeric>
using namespace std;
int main () {
char* foo[] = {"10","20","30","40","50"};
int bar[5];
int sum;
transform (foo, foo+5, bar, ptr_fun(atoi) );
sum = accumulate (bar, bar+5, 0);
cout << "sum = " << sum << endl;
return 0;
}
sum = 150
6.mem_fun
函数指针转化为函数对象
template <class S, class T> mem_fun_t<S,T> mem_fun (S (T::*f)());
template <class S, class T, class A> mem_fun1_t<S,T,A> mem_fun (S (T::*f)(A));
template <class S, class T> const_mem_fun_t<S,T> mem_fun (S (T::*f)() const);
template <class S, class T, class A> const_mem_fun1_t<S,T,A> mem_fun (S (T::*f)(A) const);
// mem_fun example
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int main () {
vector <string*> numbers;
// populate vector of pointers:
numbers.push_back ( new string ("one") );
numbers.push_back ( new string ("two") );
numbers.push_back ( new string ("three") );
numbers.push_back ( new string ("four") );
numbers.push_back ( new string ("five") );
vector <int> lengths ( numbers.size() );
transform (numbers.begin(), numbers.end(), lengths.begin(), mem_fun(&string::length));
for (int i=0; i<5; i++) {
cout << *numbers[i] << " has " << lengths[i] << " letters.\n";
}
// deallocate strings:
for (vector<string*>::iterator it = numbers.begin(); it!=numbers.end(); ++it)
delete *it;
return 0;
}
one has 3 letters.
two has 3 letters.
three has 5 letters.
four has 4 letters.
five has 4 letters.
7.mem_fun_ref
当容器中存放的是对象实体的时候用mem_fun_ref,当容器中存放的是对象的指针的时候用mem_fun。
// mem_fun_ref example
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int main () {
vector<string> numbers;
// populate vector:
numbers.push_back("one");
numbers.push_back("two");
numbers.push_back("three");
numbers.push_back("four");
numbers.push_back("five");
vector <int> lengths (numbers.size());
transform (numbers.begin(), numbers.end(), lengths.begin(), mem_fun_ref(&string::length));
for (int i=0; i<5; i++) {
cout << numbers[i] << " has " << lengths[i] << " letters.\n";
}
return 0;
}
该例子中string没有*是实体,而mem_fun的例子中string* 容器中放的是string对象的指针.
4.工具类型
1.unary_negate
// unary_negate example
#include <iostream> // std::cout
#include <functional> // std::unary_negate
#include <algorithm> // std::count_if
struct IsOdd_class {
bool operator() (const int& x) const {return x%2==1;}
typedef int argument_type;
} IsOdd_object;
int main () {
std::unary_negate<IsOdd_class> IsEven_object (IsOdd_object);
int values[] = {1,2,3,4,5};
int cx;
cx = std::count_if ( values, values+5, IsEven_object );
std::cout << "There are " << cx << " elements with even values.\n";
`
return 0;
}
There are 2 elements with even values
2.binary_negate
template <class Predicate> class binary_negate
: public binary_function <typename Predicate::first_argument_type,
typename Predicate::second_argument_type, bool>
{
protected:
Predicate fn_;
public:
explicit binary_negate ( const Predicate& pred ) : fn_ (pred) {}
bool operator() (const typename Predicate::first_argument_type& x,
const typename Predicate::second_argument_type& y) const
{ return !fn_(x,y); }
};
// binary_negate example
#include <iostream> // std::cout
#include <functional> // std::binary_negate, std::equal_to
#include <algorithm> // std::mismatch
#include <utility> // std::pair
int main () {
std::equal_to<int> equality;
std::binary_negate < std::equal_to<int> > nonequality (equality);
int foo[] = {10,20,30,40,50};
int bar[] = {0,15,30,45,60};
std::pair<int*,int*> firstmatch,firstmismatch;
firstmismatch = std::mismatch (foo,foo+5,bar,equality);
firstmatch = std::mismatch (foo,foo+5,bar,nonequality);
std::cout << "First mismatch in bar is " << *firstmismatch.second << "\n";
std::cout << "First match in bar is " << *firstmatch.second << "\n";
return 0;
}
First mismatch in bar is 0
First match in bar is 30
3.binder1st/binder2nd
分别是绑定第一个和第二个参数
template <class Operation> class binder1st
: public unary_function <typename Operation::second_argument_type,
typename Operation::result_type>
{
protected:
Operation op;
typename Operation::first_argument_type value;
public:
binder1st ( const Operation& x,
const typename Operation::first_argument_type& y) : op (x), value(y) {}
typename Operation::result_type
operator() (const typename Operation::second_argument_type& x) const
{ return op(value,x); }
};
// binder1st example
#include <iostream>
#include <functional>
#include <algorithm>
using namespace std;
int main () {
binder1st < equal_to<int> > equal_to_10 (equal_to<int>(),10);
int numbers[] = {10,20,30,40,50,10};
int cx;
cx = count_if (numbers,numbers+6,equal_to_10);
cout << "There are " << cx << " elements equal to 10.\n";
return 0;
}
There are 2 elements equal to 10.
binder2nd
template <class Operation> class binder2nd
: public unary_function <typename Operation::first_argument_type,
typename Operation::result_type>
{
protected:
Operation op;
typename Operation::second_argument_type value;
public:
binder2nd ( const Operation& x,
const typename Operation::second_argument_type& y) : op (x), value(y) {}
typename Operation::result_type
operator() (const typename Operation::first_argument_type& x) const
{ return op(x,value); }
};
其他类似binder1st
4.pointer_to_unary_function/pointer_to_binary_function
pointer_to_unary_function
template <class Arg, class Result>
class pointer_to_unary_function : public unary_function <Arg,Result>
{
protected:
Result(*pfunc)(Arg);
public:
explicit pointer_to_unary_function ( Result (*f)(Arg) ) : pfunc (f) {}
Result operator() (Arg x) const
{ return pfunc(x); }
};
pointer_to_binary_function
template <class Arg1, class Arg2, class Result>
class pointer_to_binary_function : public binary_function <Arg1,Arg2,Result>
{
protected:
Result(*pfunc)(Arg1,Arg2);
public:
explicit pointer_to_binary_function ( Result (*f)(Arg1,Arg2) ) : pfunc (f) {}
Result operator() (Arg1 x, Arg2 y) const
{ return pfunc(x,y); }
};
例子:
// pointer_to_binary_function example
#include <iostream>
#include <functional>
#include <algorithm>
#include <cmath>
using namespace std;
int main () {
pointer_to_binary_function <double,double,double> PowObject (pow);
double numbers[] = {1.0, 2.0, 3.0, 4.0, 5.0};
double squares[5];
transform (numbers, numbers+5, squares, bind2nd(PowObject,2) );
for (int i=0; i<5; i++)
cout << squares[i] << " ";
cout << endl;
return 0;
}
5.const代表成员函数是否为const;fun后有1代表单个参数成员函数,没有1代表无参成员函数;ref和pointer代表是指针还是对象实体(这些类模板分别是对应的去掉_t的类模板的函数对象的类型)
- mem_fun_t/mem_fun1_t
- const_mem_fun_t/const_mem_fun1_t
- mem_fun_ref_t/mem_fun1_ref_t
- const_mem_fun_ref_t/const_mem_fun1_ref_t
template <class S, class T>
class mem_fun_t : public unary_function <T*,S>
{
S (T::*pmem)();//const加在这里表示const成员函数
public:
explicit mem_fun_t ( S (T::*p)() ) : pmem (p) {}
S operator() (T* p) const
{ return (p->*pmem)(); }
};
其他类似.