std::bind模板函数是一个通用的函数适配器,是用一个可调用对象及其参数,生成一个新的可调用对象,以适应模板。
#include <iostream>
#include <string>
#include <functional>
using namespace std;
//普通函数
void show(int a, const string& str)
{
std::cout << a << str << std::endl;
}
class AA
{
public:
static void show(int a, const string& str)
{
std::cout << a << str << std::endl;
}
void operator()(int a, const string& str)
{
std::cout << a << str << std::endl;
}
void show1(int a, const string& str)
{
std::cout << a << str << std::endl;
}
};
int main()
{
//包装器包装普通成员函数
void(*fp)(int, const string&) = show;
std::function<void(int, const string&)> fn1 = show;
std::function<void(int, const string&)> fn11 = bind(show, placeholders::_1, placeholders::_2);
std::function<void(const string&)> fn111 = bind(show, 2, placeholders::_1);
std::function<void(int, const string&, int)> fn1111 = bind(show, placeholders::_1, placeholders::_2);
fn1(1, "你好");
fn11(1111, "你好");
fn111("你好"); fn1111(1111111,"你好",90);
//包装类的静态成员变量
std::function<void(int, const string&)> fn2 = AA::show;
std::function<void(int, const string&)> fn22 = bind(AA::show, placeholders::_1, placeholders::_2);
fn2(2, "你好");
fn22(2, "你好");
//包装仿函数
AA aa;
std::function<void(int, const string&)> fn3 = aa;
std::function<void(int, const string&)> fn33 = bind(aa, placeholders::_1, placeholders::_2);
fn3(3, "你好");
fn33(3, "你好");
//包装lambda函数
std::function<void(int, const string&)> fn5 = [](int a, const string& str) {
std::cout << a << str << std::endl;
};
std::function<void(int, const string&)> fn55 = bind([](int a, const string& str) {
std::cout << a << str << std::endl;
}, placeholders::_1, placeholders::_2);
fn5(4, "你好");
fn55(4, "你好");
//包装类的非静态成员函数
AA a;
std::function<void(AA&, int, const string&)> fn6 = &AA::show1;
std::function<void(int, const string&)> fn66 = bind(&AA::show1, &a, placeholders::_1, placeholders::_2);
fn6(a, 5, "你好");
fn66(55555555, "你好");
std::function<void(int, const string&)> fn7;
try
{
fn7(1, "");
}
catch (std::bad_function_call except)
{
std::cout << "functionName;" << __func__ << ",Line:" << __LINE__ << except.what() << endl;
}
return 0;
}
应用场景一:可变函数与参数
#include <iostream>
#include <string>
#include <functional>
using namespace std;
//普通函数
void show(int a, const string& str)
{
std::cout << a << str << std::endl;
}
void show0(int a)
{
std::cout << a << std::endl;
}
class AA
{
public:
void show1(int a, const string& str)
{
std::cout << a << str << std::endl;
}
};
template<typename Fn, typename ...Args>
auto show3(Fn&& fn, Args&&...args)
{
cout << "************\n";
auto f = bind(forward<Fn>(fn), forward<Args>(args)...);//args...作为整体传递
f();
cout << "************\n";
return f;
}
//可变参数
int main()
{
show3(show, 1, "dfdfd");
show3(show0, 89);
AA a;
show3(&AA::show1, &a, 89, "hello");
return 0;
}
应用场景二:回调函数的实现
在消息队列和网络库的框架中,当接收到消息(报文)时,回调用户自定义的函数对象,把消息(报文)参数传给它,由它决定如何处理。
#include <iostream>
#include <string>
#include <thread> // 线程类头文件。
#include <mutex> // 互斥锁类的头文件。
#include <deque> // deque容器的头文件。
#include <queue> // queue容器的头文件。
#include <condition_variable> // 条件变量的头文件。
#include <functional>
using namespace std;
void show(const string& message) { // 处理业务的普通函数
cout << "处理数据:" << message << endl;
}
class FrameWork
{
public:
FrameWork(const string& message)
:m_str(message)
{}
void dowork(const string& message)
{
// 处理出队的数据(把数据消费掉)。
std::cout << "这是回调函数处理的代码,业务层.\t"
<< message
<< "\t"
<< m_str\
<< std::endl;
}
private:
string m_str;
};
class Bussiness
{
function<void(const string&)> m_callback; // 回调函数对象。
public:
// 注册回调函数,回调函数只有一个参数(消费者接收到的数据)。
template<typename Fn, typename ...Args>
void callback(Fn&& fn, Args&&...args) {
m_callback = bind(forward<Fn>(fn), forward<Args>(args)..., std::placeholders::_1); // 绑定回调函数。
}
void dowork(const string& message)
{
std::cout << "***********框架层开始处理代码*************\n";
// 处理出队的数据(把数据消费掉)。
if (m_callback) m_callback(message); // 回调函数,把收到的数据传给它。
std::cout << "************框架层结束处理代码************\n";
}
};
int main()
{
Bussiness aa;
FrameWork b("hello, it's me");
aa.callback(&FrameWork::dowork, &b); // 把类成员函数BB::show()注册为回调函数。
aa.dowork("mesage");
return 0;
}