C++11中std::bind的使用

2023-11-11

std::bind函数是用来绑定函数调用的某些参数的。std::bind它可以预先把指定可调用实体的某些参数绑定到已有的变量,产生一个新的可调用实体。它绑定的参数的个数不受限制,绑定的具体哪些参数也不受限制,由用户指定

std::bind:(1)、将函数、成员函数和闭包转成function函数对象;(2)、将多元(n>1)函数转成一元函数或者(n-1)元函数。

std::bind本身是一种延迟计算的思想,它本身可以绑定普通函数、全局函数、静态函数、类静态函数甚至是类成员函数。无法使用std::bind绑定一个重载函数的参数,必须显式地指出需要绑定的重载函数的版本。成员函数区别于普通函数的一个特殊之处在于,其第一个参数必须是该类型的一个对象(或对象的指针或引用)。

std::bind接受一个函数(或者函数对象,或者任何你可以通过"(…)"符号调用的事物),生成一个其有某一个或多个函数参数被”绑定”或重新组织的函数对象。绑定的参数将会以值传递的方式传递给具体函数,占位符将会以引用传递。

std::bind需要注意事项:

(1)、bind预先绑定的参数需要传具体的变量或值进去,对于预先绑定的参数,是pass-by-value的;

(2)、对于不事先绑定的参数,需要传std::placeholders进去,从_1开始,依次递增。placeholder是pass-by-reference的;

(3)、bind的返回值是可调用实体,可以直接赋给std::function对象;

(4)、对于绑定的指针、引用类型的参数,使用者需要保证在可调用实体调用之前,这些参数是可用的;

(5)、类的this可以通过对象或者指针来绑定。

std::bind: Each argument may either be bound to a value or be a placeholder:

(1)、If bound to a value, calling the returned function object will always use that value as argument;

(2)、If a placeholder, calling the returned function object forwards an argument passed to the call (the one whose order number is specified by the placeholder).

std::bind receives a pointer to a function (it also can be a lambda expression or a functor) and receives a list of parameters that pass it to the function. As result, bind returns a new function object with a different prototype because all the parameters of the function were already specified.

A placeholder is an object that specifies the number of parameter in the bound function that will be used to enter this parameter.

std::bind is a Standard Function Objects that acts as a Functional Adaptor i.e. it takes a function as input and returns a new function Object as an output with with one or more of the arguments of passed function bound or rearranged.

下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:

#include "bind.hpp"
#include <iostream>
#include <string>
#include <functional> // std::bind
#include <random>
#include <memory>
#include <algorithm>

//
// reference: http://en.cppreference.com/w/cpp/utility/functional/bind
static void f(int n1, int n2, int n3, const int& n4, int n5)
{
	std::cout << n1 << ' ' << n2 << ' ' << n3 << ' ' << n4 << ' ' << n5 << '\n';
}

static int g(int n1)
{
	return n1;
}

struct Foo_bind {
	void print_sum(int n1, int n2)
	{
		std::cout << n1 + n2 << '\n';
	}
	int data = 10;
};

int test_bind1()
{
	using namespace std::placeholders;  // for _1, _2, _3...

	// demonstrates argument reordering and pass-by-reference
	int n = 7;
	// (_1 and _2 are from std::placeholders, and represent future
	// arguments that will be passed to f1)
	auto f1 = std::bind(f, _2, _1, 42, std::cref(n), n);
	n = 10;
	f1(1, 2, 1001); // 1 is bound by _1, 2 is bound by _2, 1001 is unused
	// makes a call to f(2, 1, 42, n, 7)

	// nested bind subexpressions share the placeholders
	auto f2 = std::bind(f, _3, std::bind(g, _3), _3, 4, 5);
	f2(10, 11, 12);

	// common use case: binding a RNG with a distribution
	std::default_random_engine e;
	std::uniform_int_distribution<> d(0, 10);
	std::function<int()> rnd = std::bind(d, e); // a copy of e is stored in rnd
	for (int n = 0; n<10; ++n)
		std::cout << rnd() << ' ';
	std::cout << '\n';

	// bind to a pointer to member function
	Foo_bind foo;
	auto f3 = std::bind(&Foo_bind::print_sum, &foo, 95, _1);
	f3(5);

	// bind to a pointer to data member
	auto f4 = std::bind(&Foo_bind::data, _1);
	std::cout << f4(foo) << '\n';

	// smart pointers can be used to call members of the referenced objects, too
	//std::cout << f4(std::make_shared<Foo_bind>(foo)) << '\n'
	//	<< f4(std::make_unique<Foo_bind>(foo)) << '\n';

	return 0;
}

///
// reference: http://www.cplusplus.com/reference/functional/bind/
// a function: (also works with function object: std::divides<double> my_divide;)
double my_divide(double x, double y) { return x / y; }

struct MyPair {
	double a, b;
	double multiply() { return a*b; }
};

int test_bind2()
{
	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';                // 10

	return 0;
}

/
// reference: https://oopscenities.net/2012/02/24/c11-stdfunction-and-stdbind/
static void show(const std::string& a, const std::string& b, const std::string& c)
{
	std::cout << a << "; " << b << "; " << c << std::endl;
}

int test_bind3()
{
	using namespace std::placeholders;

	// Thanks to the placeholders, you can change the order of the arguments passed as parameters to a bound function.
	auto x = bind(show, _1, _2, _3);
	auto y = bind(show, _3, _1, _2);
	auto z = bind(show, "hello", _2, _1);

	x("one", "two", "three");
	y("one", "two", "three");
	z("one", "two");

	return 0;
}

/
// reference: http://stackoverflow.com/questions/22422147/why-is-stdbind-not-working-without-placeholders-in-this-example-member-functi
static void f_(int a, int b, int c)
{
	fprintf(stdout, "a = %d, b = %d, c = %d\n", a, b, c);
}

struct foo_bind
{
	void f() const { fprintf(stdout, "foo_bind\n"); };
};

int test_bind4()
{
	using namespace std::placeholders;

	// The first parameter of std::bind() is the function to be called, and the rest are the arguments of the call.
	std::function<void()> f_call = std::bind(f_, 1, 2, 3);
	f_call(); //Equivalent to f_(1,2,3)

	// If you need to specify that some parameters have to be specified at the call point,
	// you have to use placeholders to represent that parameters
	std::function<void(int, int, int)> f_call2 = std::bind(f_, _1, _2, _3);
	f_call2(1, 2, 3); //Same as f_(1,2,3)

	// Note that the numbers of the placeholders specify the number of the parameter at the call point.
	// The first parameter of the call point is identified by _1, the second by _2, and so on.
	// This could be used to specify parameters in different ways, reordering the parameters of a function call, etc.
	std::function<void(int, int)> f_call3 = std::bind(f_, _1, 2, _2);
	f_call3(1, 3); //Equivalent to f_( 1 , 2 , 3 );

	std::function<void(int, int, int)> reordered_call = std::bind(f_, _3, _2, _1);
	reordered_call(3, 2, 1); //Same as f_( 1 , 2 , 3 );

	// std::bind() could be used to bind a member function to the object used to call it
	foo_bind myfoo;
	std::function<void()> f = std::bind(&foo_bind::f, std::cref(myfoo));
	f();

	return 0;
}

/
// reference: https://msdn.microsoft.com/en-us/library/bb982702.aspx
static void square(double x)
{
	std::cout << x << "^2 == " << x * x << std::endl;
}

static void product(double x, double y)
{
	std::cout << x << "*" << y << " == " << x * y << std::endl;
}

int test_bind5()
{
	using namespace std::placeholders;

	double arg[] = { 1, 2, 3 };

	std::for_each(&arg[0], arg + 3, square);
	std::cout << std::endl;

	std::for_each(&arg[0], arg + 3, std::bind(product, _1, 2));
	std::cout << std::endl;

	std::for_each(&arg[0], arg + 3, std::bind(square, _1));

	return (0);
}

GitHubhttps://github.com/fengbingchun/Messy_Test

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++11中std::bind的使用 的相关文章

随机推荐

  • UWB的定位算法(简单详细易懂)

    系列文章目录 文章目录 系列文章目录 前言 一 控制部分 二 UWB 的测距原理是什么 三 TOF 数学计算 四 Trilateration 三边测量法的原理与计算方法 TDOA平面 1 三边测量法的缺陷是 2 Z 轴准确度比 X 轴 Y
  • 多项目同时进行,如何做好项目管理?

    大部分企业在运营过程中一般会存在多个项目并行推进的情况 一段时间只运营一个项目的情况已经很少 无论是对项目管理者还是项目执行者而言 多项目同时进行比单项目运行更具挑战 多项目管理一般会存在各项目之间抢资源 资源冲突 资源分配不合理 可能存在
  • 使用node-forge pki进行RSA加密

    先放npm官方文档 www npmjs com package node forge 在知道RSA加密的大致原理后 再往下看 使用例子 简单写个方法 引入依赖 import forge from node forge base64转换 一般
  • 第十届蓝桥杯决赛B组:排列数

    这题我们用动态规划做 首先我们来找规律 对于一个递增的数列 如123456 我们插入一个数 这个数大于数列中所有的数 这里插入7 如果不插在两端 1 6 的数两侧 则增加了两个拐点 如1273456 插在 1 6 的内测 有两种情况 如17
  • win2008+IIS7.5+VS2013+4.5netframework,HTTP 错误 404.0 - Not Found 错误代码 0x80070002 解决办法

    win2008系统IIS7 5部署网站后访问首页正常 但访问其他地址时出错 如 访问http localhost ARCIMS Website lanzfc veiwers htm出错 错误如下 应用程序 DEFAULT WEB SITE
  • [论文阅读笔记77]LoRA:Low-Rank Adaptation of Large Language Models

    1 基本信息 题目 论文作者与单位 来源 年份 LoRA Low Rank Adaptation of Large Language Models microsoft International Conference on Learning
  • 2019新年flag

    多的不说了 直接立flag吧 看看年底的时候完成情况 dubbo的细节回顾结合dubbo面试题进行学习 netty的项目总结和源码学习 es的源码学习 系统学习 结合脑图 要有输出 数量不在多 在于精 多运动 多读书 少看直播
  • UI Automation编程辅助工具Inspect的下载和使用

    UIAutomation微软提供的UI自动化库 主要用AutomationElement类来表示UI 自动化目录树中的一个UI自动化元素 NET Windows的窗体应用程序和WPF应用程序 Inspect是一款类似于SPY的界面捕捉工具
  • 拉普拉斯的原理

    拉普拉斯是一种二阶导数算子 是一个与方向无关的各向同性 旋转轴对称 边缘检测算子 若只关心边缘点的位置而不顾其周围的实际灰度差时 一般选择该算子进行检测 拉普拉斯算子为二阶差分 其方向信息丢失 常产生双像素 对噪声有双倍加强作用 因此它很少
  • ng-model指令

    ng model指令作用是绑定HTML表单元素到AngularJS应用程序数据中 即 scope变量中 语法
  • Ispci命令详解

    说明 lspci 是一个用来显示系统中所有PCI总线设备或连接到该总线上的所有设备的工具 参数 v 使得 lspci 以冗余模式显示所有设备的详细信息 vv 使得 lspci 以过冗余模式显示更详细的信息 事实上是 PCI 设备能给出的所有
  • 二进制数组的操作

    ES6之前是不能通过代码直接操作二进制数据的 为了方便开发者可以直接操作二进制数据 ES6提出了三个操作二进制数据的接口 ArrayBuffer TypedArray和DataView ArrayBuffer ArrayBuffer代表储存
  • mysql设置了utf8mb4还是报错_详解JDBC对Mysql utf8mb4字符集的处理

    写在前面 在开发微信小程序的时候 评论服务模块希望添加上emoji表情 但是emoji表情是4个字节长度的 所以需要进行设置 当前项目是JAVA编写 使用JDBC连接操作数据库 如下针对的JDBC操作的解决方案 一 JDBC的URL的正常操
  • springboot_使用servlet的两种方式

    虽然在springboot中我们使用Controller可以应付大部分的需求 但servlet等也是必不可少的 在springboot中使用servlet有两种方式 第一种 用注解方式创建一个servlet 并在注解中声明其url 在App
  • git stash 暂存命令

    一个分支切换另一个分支的时候 当时分支并没有完成任务 我们就可以把他暂存下来 暂存代码 git stash m 暂存信息 也可以git stash 查看所有的存储列表 git stash list 释放最新的存储 工作区是这次存储对应的代码
  • dns配置

    dns配置文件详解 dns配置文件默认在 etc named conf中 vim etc named conf options 影响zone设置 listen on port 53 127 0 0 1 监听端口和ip 若监听所有 则 any
  • 知识梳理:链接形式

    驱动开发 链接 PowerPC介绍
  • 计算机专业建议买苹果笔记本吗,笔记本买win还是买Mac?也许可以参考这些建议...

    原标题 笔记本买win还是买Mac 也许可以参考这些建议 笔记本买win还是买Mac 相信各位在买笔记本的时候 都曾经在 Windows 和 Mac 之间犹豫过 其实 这个问题并没有标准答案 毕竟适合自己的才是最好的 那么 最后您选择了哪个
  • 皮卡堂显示服务器超时,皮卡堂服务生职业

    皮卡堂服务生职业赶快点击皮卡堂 开始玩游戏吧 服务生1级 职业经验 lt 500 吆喝 1 学习了服务生后 可以在聊天输入框处设置3句快捷语言 2 右键单击自己 可以选择举三个固定的礼仪牌 分别显示 请您点菜 欢迎光临 谢谢惠顾 请您用餐
  • C++11中std::bind的使用

    std bind函数是用来绑定函数调用的某些参数的 std bind它可以预先把指定可调用实体的某些参数绑定到已有的变量 产生一个新的可调用实体 它绑定的参数的个数不受限制 绑定的具体哪些参数也不受限制 由用户指定 std bind 1 将