仿函数和配接器的使用182

要想使用stl配接器算法,unary_function、binary_function的仿函数就必须使用.

先来看STL已经提供的仿函数

算法类仿函数

加法: plus<T>

减法:minus<T>

乘法:multiplies<T>

除法:divides<T>

模取:modulus<T>

否定:negate<T>(一元)

关系仿函数

等于:equal_to<T>

不等于:not_equal_to<T>

大于:greater<T>

大于或等于:greater_equal<T>

小于:less<T>

小于或等于:less_equal<T>

逻辑运算仿函数

and: logical_and<T>

or: logical_or<T>

not: logical_not<T>

选择和投射

select1st<T> select2nd<T> 对于此类,是针对pair的,传入pair,并返回第一个元素或第二个元素

project1st<T> project2nd<T> 对于此类,是针对多参数的,传入俩个参数,只返回第一个元素或第二个元素

再看配接器

函数名 实际效果 实际对象
bind(_Farg0::* const _Pmd, _Arg0&& _A0) 11的新特性,auto配合万能绑定,参数能支持到20个参数,对成员函数绑定时第一个参数默认为传入对象
bind1st(const op& op, const T& x) op(x, param) binder1st(op, arg1_type(x))
bind2nd(const op& op, const T& x) op(param, x) binder2nd(op, arg2_type(x))
not1(const Pred& pred) !pred(param) unary_negate(pred)
not2(const Pred& pred) !pred(param1, param2) binary_negate(pred)
compose1(const Op1& op1, const Op2& op2) op1(op2(param)) unary_compose(op1, op2)
compose2(
const Op1& op1,
const Op2& op2,
const Op3& op3)
op1(op2(param),
op3(param))
binary_compose
(op1, op2, op3)
ptr_fun(Result(*fp)(Arg)) fp(param) pointer_to_unary_function(fp)
ptr_fun(Result(*fp)(Arg1, Arg2)) fp(param1, param2) pointer_to_binary_function(fp)
mem_fn() 11的新特性,auto配合,和bind绑定成员函数块差别不大,第一个参数默认为传入对象
mem_fun(S (T::*f)()) (param->*f)() mem_fun_t(f)
mem_fun(S (T::*f)() const) (param->*f)() const_mem_fun_t(f)
mem_fun_ref(S (T::*f)()) (param.*f)() mem_fun_ref_t(f)
mem_fun_ref(S (T::*f)() const) (param.*f)() const_mem_fun_ref_t(f)
mem_fun1(S (T::*f)(A)) (param->*f)(x) mem_fun1_t(f)
mem_fun1(S (T::*f)(A) const) (param->*f)(x) const_mem_fun1_t(f)
mem_fun1_ref(S (T::*f)(A)) (param.*f)(x) mem_fun1_ref_t(f)
mem_fun1_ref(S (T::*f)(A) const) (param.*f)(x) const_mem_fun1_ref_t(f)

bind


++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
double my_divide (double x, double y) {return x/y;}
struct MyPair {
double a,b;
double multiply() {return a*b;}
};
struct Foo {
void print_sum(int n1, int n2)
{
std::cout << n1+n2 << '\n';
}
int data = 10;
};
int main () {
using namespace std::placeholders; //这里注意 adds visibility of _1, _2, _3,...
// binding functions:
auto fn_five = std::bind (my_divide,10,2); // returns 10/2
std::cout << fn_five() << '\n'; // 5
auto fn_half = std::bind (my_divide,_1,2); // returns x/2
std::cout << fn_half(10) << '\n'; // 5
auto fn_invert = std::bind (my_divide,_2,_1); // returns y/x
std::cout << fn_invert(10,2) << '\n'; // 0.2
auto fn_rounding = std::bind<int> (my_divide,_1,_2); // returns int(x/y)
std::cout << fn_rounding(10,3) << '\n'; // 3
MyPair ten_two {10,2};
// binding members:
auto bound_member_fn = std::bind (&MyPair::multiply,_1); // returns x.multiply()
std::cout << bound_member_fn(ten_two) << '\n'; // 20
auto bound_member_data = std::bind (&MyPair::a,ten_two); // returns ten_two.a
std::cout << bound_member_data() << '\n';
Foo foo;
auto f3 = std::bind(&Foo::print_sum, foo, 95, _1);
f3(5);


bind1st

bind2nd


++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int fun(int a, int b)
{
cout << a - b << endl;;
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[] = {1, 2, 3, 4};
for_each(a, a+4, bind1st(ptr_fun(fun), 2));//此处由于,bind1st要传入适配器,所以要么fun继承前面的多元函数,要么如此处理
for_each(a, a+4, bind2nd(ptr_fun(fun), 2));
system("pause");
return 0;
}


not1


++
1
2
3
count_if(a, a+5, not1(bind2nd(less<int>(), 4)))//统计大于等于4的个数


not2


++
1
2
3
int h = accumulate(a, a+5, 4, not2(ptr_fun(fun)));//此中的not2然并卵作用,主要是自己无法想到好的二元算法了


compose1

compose2


它是GNU的所以vs STL没有,有源码如下++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
template<class _Fn1, class _Fn2>
class unary_compose
: public unary_function<typename _Fn2::argument_type,
typename _Fn1::result_type>
{ // functor adapter _Func(stored, right)
public:
typedef unary_function<typename _Fn2::argument_type,
typename _Fn1::result_type> _Base;
typedef typename _Base::argument_type argument_type;
typedef typename _Base::result_type result_type;
unary_compose(const _Fn1& _Func1,
const _Fn2& _Func2)
: op1(_Func1), op2(_Func2)
{ // construct from functor and left operand
}
result_type operator()(const argument_type& _Value) const
{ // apply functor to operands
return (op1(op2(_Value)));
}
result_type operator()(argument_type& _Value) const
{ // apply functor to operands
return (op1(op2(_Value)));
}
protected:
_Fn1 op1; // the functor to apply
_Fn2 op2; // the functor to apply
};
template<class _Fn1,
class _Fn2> inline
unary_compose<_Fn1, _Fn2> compose1(const _Fn1& _Func1, const _Fn2& _Func2)
{ // return a unary_compose functor adapter
return (unary_compose<_Fn1, _Fn2>(_Func1, _Func2));
}
for_each(a, a+5, compose1(bind2nd(multiplies<int>(), 2), bind2nd(plus<int>(), 2)));


ptr_fun

上面已经有代码演示,无需


mem_fun


成员对象必须是指针++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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;


mem_fun1

这个函数并不像实际效果那样,它应该是俩个参数,且各个绑定不同。
此函数11之后被淘汰

++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
numbers.push_back ( new dd );
numbers.push_back ( new dd );
class dd {
public:
dd() {}
~dd() {}
int aa(int a) {
cout << a - 1 << endl;
return a - 1;
}
};
for_each (numbers.begin(), numbers.end(), bind2nd(mem_fun1(&dd::aa), 2));//如此便是循环执行:iterator->aa(2);
////////////////////////////
numbers.push_back ( new dd );
numbers.push_back ( new dd );
class aa {
public:
aa() {}
~aa() {}
int dd(dd* a) {
cout << 33 << endl;
return 0;
}
};
aa s;
for_each (numbers.begin(), numbers.end(), bind1st(mem_fun1(&aa::dd), &s));//如此便是循环执行:(&s)->dd(iterator);

mem_fun_ref

mem_fun1_ref

它们和mem_fun区别在于,iterator是对象,而不是指针。
mem_fun1_ref此函数11之后被淘汰


mem_fn


++
1
2
3
4
5
dd a;
auto triple = std::mem_fn(&dd::aa);
cout << triple(a, 2) << endl;//以a为调用对象,传入2

// //