1.5 std::function和bind绑定器
本文为图书《深入应用C++11:代码优化与工程级应用 祁宇编著》1.5章内容笔记
1.5.1 可调用函数
可调用对象
- 函数指针
- 具有operator()成员函数的类对象(仿函数)
- 可被转化为函数指针的类对象
- 类成员(函数)指针
代码:
#include <iostream>
#include <map>
using namespace std;
//1.5.1
/*可调用对象
(1)函数指针
(2)具有operator()成员函数的类对象(仿函数)
(3)可被转化为函数指针的类对象
(4)类成员(函数)指针
*/
void func(void)
{
cout << "func" << endl;
}
struct Foo
{
void operator()(void)
{
cout << "Foo" << endl;
}
};
struct Bar
{
using fr_t = void(*)(void);
static void func(void)
{
cout << "Bar" << endl;
}
operator fr_t(void)
{
return func;
}
};
struct A
{
int a;
void mem_func(void)
{
cout << "A:" <<a<< endl;
}
};
int main()
{
void (*func_ptr)(void) = &func;//1.函数指针
func_ptr();
Foo foo;//仿函数
foo();
Bar bar;//3.可被转换为函数指针的类对象
bar();
void(A::* mem_func_ptr)(void) = &A::mem_func;//4.类成员函数指针
int A::* mem_obj_ptr = &A::a;//或者是类成员指针
A aa;
aa.*mem_obj_ptr = 3;
(aa.*mem_func_ptr)();
return 0;
}
1.5.2 std::function
std::function是可调用对象的包装器。它是一个类模板,可以容纳除了类成员(函数)指针之外的所有可调用对象。通过指定它的模板参数,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延时执行它们。
#include <iostream>
#include <functional>//std::function
using namespace std;
//1.5.1
/*可调用对象
(1)函数指针
(2)具有operator()成员函数的类对象(仿函数)
(3)可被转化为函数指针的类对象
(4)类成员(函数)指针
*/
//__FUNCTION__ 返回函数名
void func(void)
{
cout << __FUNCTION__ << endl;
}
class Foo
{
public:
static int foo_func(int a)
{
cout << __FUNCTION__ << "("<<a<<")"<<endl;
return a;
}
};
class Bar
{
public:
int operator()(int a)
{
cout << __FUNCTION__ << "(" << a << ")" << endl;
return a;
}
};
int main()
{
//格式:std::function<返回类型(参数类型)>函数名
std::function<void(void)>fr1 = func;//绑定一个普通函数
fr1();
//绑定一个类的静态成员函数
std::function<int(int)>fr2 = Foo::foo_func;
fr2(123);
Bar bar;
fr2 = bar;
fr2(321);
return 0;
}
std::function作为回调函数
#include <iostream>
#include <functional>//std::function
using namespace std;
class A
{
std::function<void()>callback_;
public:
A(const std::function<void()>& f) :callback_(f) {}
void notify(void)
{
callback_();
}
};
class Foo
{
public:
void operator()()
{
cout << __FUNCTION__ << endl;
}
};
int main()
{
Foo foo;
A aa(foo);
aa.notify();
return 0;
}
std::function 作为函数入参
#include <iostream>
#include <functional>//std::function
using namespace std;
void call_when_even(int x, const::function<void(int)>& f)
{
if (!(x & 1))//x%2==0
{
f(x);
}
}
void optput(int x)
{
std::cout << x << " ";
}
int main()
{
for (int i = 0; i < 10; ++i)
{
call_when_even(i, optput);
}
std::cout << std::endl;
return 0;
}
1.5.3 std::bind绑定器
std::bind用来将可调用对象与其参数一起进行绑定
- 将可调用对象与其参数一起邦定成一个仿函数;
- 将多元(参数个数为n,n>1)可调用对象转成一元或者(n-1)元可调用对象,即只绑定部分参数;
#include <iostream>
#include <functional>//std::function
using namespace std;
void call_when_even(int x, const::function<void(int)>& f)
{
if (!(x & 1))//x%2==0
{
f(x);
}
}
void optput(int x)
{
std::cout << x << " ";
}
void optput_add_2(int x)
{
std::cout << x + 2 << " ";
}
int main()
{
{
auto fr = std::bind(optput, std::placeholders::_1);//std::placeholders占位符,c++11中有29个占位符,分别是_1~_29,代表传入第几个参数
//使用auto承接返回值,如此可不关心返回值类型
for (int i = 0; i < 10; ++i)
{
call_when_even(i, fr);
}
std::cout << std::endl;
}
{
auto fr2 = std::bind(optput_add_2, std::placeholders::_1);
for (int i = 0; i < 10; ++i)
{
call_when_even(i, fr2);
}
std::cout << std::endl;
}
return 0;
}
使用std::placeholders来决定空位参数将会属于调用发生时的第几个参数
#include <iostream>
#include <functional>//std::function
using namespace std;
void output(int x,int y)
{
std::cout << x << " "<<y<<endl;
}
int main()
{
std::bind(output, 1, 2)();//1 2
std::bind(output, std::placeholders::_1, 2)(1);//1 2
std::bind(output, 2, std::placeholders::_1)(1);//2 1
//std::bind(output, 2, std::placeholders::_2)(1);//error 调用时没有第二个参数
std::bind(output, 2, std::placeholders::_2)(1,2);//2 2 调用时的第一个参数被吞掉了
std::bind(output, std::placeholders::_1, std::placeholders::_1)(1,2);//1 1
std::bind(output, std::placeholders::_2, std::placeholders::_2)(1, 2);//2 2
std::bind(output, std::placeholders::_1, std::placeholders::_2)(1, 2);//1 2
std::bind(output, std::placeholders::_2, std::placeholders::_1)(1, 2);//2 1
return 0;
}
std::bind和std::function配合使用,将类的成员函数的指针和其对象进行绑定,转换为一个仿函数放入std::function对象中存储
#include <iostream>
#include <functional>//std::function
using namespace std;
class A
{
public:
int i_;
void output(int x, int y)
{
std::cout << x << " " << y << endl;
}
};
int main()
{
A a;
std::function<void(int, int)>fr = std::bind(&A::output,&a, std::placeholders::_1, std::placeholders::_2);
/*
// FUNCTION TEMPLATE bind (implicit return type)
template <class _Fx, class... _Types>
_NODISCARD _Binder<_Unforced, _Fx, _Types...> bind(_Fx&& _Func, _Types&&... _Args) {
return _Binder<_Unforced, _Fx, _Types...>(_STD forward<_Fx>(_Func), _STD forward<_Types>(_Args)...);
}
// FUNCTION TEMPLATE bind (explicit return type)
template <class _Ret, class _Fx, class... _Types>
_NODISCARD _Binder<_Ret, _Fx, _Types...> bind(_Fx&& _Func, _Types&&... _Args) {
return _Binder<_Ret, _Fx, _Types...>(_STD forward<_Fx>(_Func), _STD forward<_Types>(_Args)...);
}
*/
fr(1, 2);//指向类成员函数的指针
std::function<int&(void)>fr_i = std::bind(&A::i_, &a);
fr_i() = 123;
std::cout << a.i_ << std::endl;
return 0;
}
std::bind 组合使用
#include <iostream>
#include <vector>
#include <functional>//std::function
#include <algorithm>
using namespace std;
int main()
{
std::vector<int>vec = { 2,1,3,5,4,6,10,8,7,9 };
int count = std::count_if(vec.begin(), vec.end(), std::bind(std::less<int>(),std::placeholders::_1, 5));//<5
cout<< count <<endl;//count = 4
count = std::count_if(vec.begin(), vec.end(), std::bind(std::less<int>(), 5, std::placeholders::_1));//>5
cout << count << endl;//count = 5
//找出vec_2数组中大于5小于9的个数
std::vector<int>vec_2 = { 2,1,3,5,4,6,10,8,7,9,11,12 };
using std::placeholders::_1;
auto f_1 = std::bind(std::greater<int>(), _1, 5);//判断是否大于5
auto f_2 = std::bind(std::less<int>(), _1, 9);//判断是否小于9
auto f = std::bind(std::logical_and<bool>(), f_1, f_2);//是否同时满足上述条件
count = std::count_if(vec_2.begin(), vec_2.end(), f);
cout << count << endl;
return 0;
}