c++ function和bind
bind
定义在头文件 functional 里
template<typename _Func, typename... _BoundArgs>
inline typename
_Bind_helper<__is_socketlike<_Func>::value, _Func, _BoundArgs...>::type
bind(_Func&& __f, _BoundArgs&&... __args) template<typename _Result, typename _Func, typename... _BoundArgs>
inline
typename _Bindres_helper<_Result, _Func, _BoundArgs...>::type
bind(_Func&& __f, _BoundArgs&&... __args)
函数模板 bind 生成 f 的转发调用包装器。调用此包装器等价于以一些绑定到 args 的参数调用 f 。类似于 python 的 functools.partial
参数 f 表示可调用对象(函数对象、指向函数指针、函数的引用、指向成员函数指针或指向数据成员指针)
参数 __args 表示要绑定的参数列表。未绑定参数使用命名空间 std::placeholders 的占位符 _1, _2, _3... 所替换
需要注意的是:
调用指向非静态成员函数指针或指向非静态数据成员指针时,首参数必须是引用或指针(可以包含智能指针,如 std::shared_ptr 与 std::unique_ptr),指向将访问其成员的对象。
到 bind 的参数被复制或移动,而且决不按引用传递,除非包装于 ref 或 cref
允许同一 bind 表达式中的多重占位符(例如多个 _1 ),但结果仅若对应参数( u1 )是左值或不可移动右值才良好定义。
#include <random>
#include <iostream>
#include <memory>
#include <functional> void f(int n1, int n2, int n3, const int& n4, int n5)
{
std::cout << n1 << ' ' << n2 << ' ' << n3 << ' ' << n4 << ' ' << n5 << '\n';
} int g(int n1)
{
return n1;
} struct Foo {
void print_sum(int n1, int n2)
{
std::cout << n1+n2 << '\n';
}
int data = ;
}; int main()
{
using namespace std::placeholders; // 对于 _1, _2, _3... // 演示参数重排序和按引用传递
int n = ;
// ( _1 与 _2 来自 std::placeholders ,并表示将来会传递给 f1 的参数)
auto f1 = std::bind(f, _2, _1, , std::cref(n), n);
n = ;
f1(, , ); // 1 为 _1 所绑定, 2 为 _2 所绑定,不使用 1001
// 进行到 f(2, 1, 42, n, 7) 的调用 // 嵌套 bind 子表达式共享占位符
auto f2 = std::bind(f, _3, std::bind(g, _3), _3, , );
f2(, , ); // 进行到 f(12, g(12), 12, 4, 5); 的调用 // 常见使用情况:以分布绑定 RNG
std::default_random_engine e;
std::uniform_int_distribution<> d(, );
std::function<int()> rnd = std::bind(d, e); // e 的一个副本存储于 rnd
for(int n=; n<; ++n)
std::cout << rnd() << ' ';
std::cout << '\n'; // 绑定指向成员函数指针
Foo foo;
auto f3 = std::bind(&Foo::print_sum, &foo, , _1);
f3(); // 100 // 绑定指向数据成员指针
auto f4 = std::bind(&Foo::data, _1);
std::cout << f4(foo) << '\n'; // 10 // 智能指针亦能用于调用被引用对象的成员
std::cout << f4(std::make_shared<Foo>(foo)) << '\n'; // return ;
}
function
定义在头文件 functional 里
template<typename _Res, typename... _ArgTypes>
class function<_Res(_ArgTypes...)>
类模板 std::function 是通用多态函数封装器。 std::function 的实例能存储、复制及调用任何可回调目标——函数、lambda表达式、bind表达式、其他函数对象,还可以指向成员函数指针和指向数据成员指针。
存储的可调用对象被称为 std::function 的目标。若 std::function 不含目标,则称它为空。调用空 std::function 的目标导致抛出 bad_function_call 异常。
function 满足可复制构造和可复制赋值。
#include <functional>
#include <iostream> struct Foo {
Foo(int num) : num_(num) {}
void print_add(int i) const { std::cout << num_+i << '\n'; }
int num_;
}; void print_num(int i)
{
std::cout << i << '\n';
} struct PrintNum {
void operator()(int i) const
{
std::cout << i << '\n';
}
}; int main()
{
// 存储自由函数
std::function<void(int)> f_display = print_num;
f_display(-); // -9 // 存储 lambda
std::function<void()> f_display_42 = []() { print_num(); };
f_display_42(); // 42 // 存储到 std::bind 调用的结果
std::function<void()> f_display_31337 = std::bind(print_num, );
f_display_31337(); // 31337 // 存储到成员函数的调用
std::function<void(const Foo&, int)> f_add_display = &Foo::print_add;
const Foo foo();
f_add_display(foo, ); //
f_add_display(, ); // 314160 // 存储到数据成员访问器的调用
std::function<int(Foo const&)> f_num = &Foo::num_;
std::cout << "num_: " << f_num(foo) << '\n'; // 314159 // 存储到成员函数及对象的调用
using std::placeholders::_1;
std::function<void(int)> f_add_display2 = std::bind( &Foo::print_add, foo, _1 );
f_add_display2(); // 314161 // 存储到成员函数和对象指针的调用
std::function<void(int)> f_add_display3 = std::bind( &Foo::print_add, &foo, _1 );
f_add_display3(); // 314162 // 存储到函数对象的调用
std::function<void(int)> f_display_obj = PrintNum();
f_display_obj(); //
}
c++ function和bind的更多相关文章
- 【转载】C++ function、bind和lambda表达式
本篇随笔为转载,原贴地址:C++ function.bind和lambda表达式. 本文是C++0x系列的第四篇,主要是内容是C++0x中新增的lambda表达式, function对象和bind机制 ...
- 一起Polyfill系列:Function.prototype.bind的四个阶段
昨天边参考es5-shim边自己实现Function.prototype.bind,发现有不少以前忽视了的地方,这里就作为一个小总结吧. 一.Function.prototype.bind的作用 其实 ...
- 聊聊Function的bind()
bind顾名思义,绑定. bind()方法会创建一个新函数,当这个新函数被调用时,它的this值是传递给bind()的第一个参数,它的参数是bind()的其他参数和其原本的参数. 上面这个定义最后一句 ...
- Function.prototype.bind接口浅析
本文大部分内容翻译自 MDN内容, 翻译内容经过自己的理解. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Glo ...
- C++中str1::function和bind
在C++的TR1中(TechnologyReport)中包括一个function模板类和bind模板函数,使用它们能够实现类似函数指针的功能,但却却比函数指针更加灵活,特别是函数指向类的非静态成员函数 ...
- 【转】C++ function、bind以及lamda表达式
本文是C++0x系列的第四篇,主要是内容是C++0x中新增的lambda表达式, function对象和bind机制.之所以把这三块放在一起讲,是因为这三块之间有着非常密切的关系,通过对比学习,加深对 ...
- JavaScript 函数绑定 Function.prototype.bind
ECMAScript Edition5 IE9+支持原生,作用为将一个对象的方法绑定到另一个对象上执行. Function.prototype.bind = Function.prototype.bi ...
- Function.prototype.bind
解析Function.prototype.bind 简介 对于一个给定的函数,创造一个绑定对象的新函数,这个函数和之前的函数功能一样,this值是它的第一个参数,其它参数,作为新的函数的给定参数. b ...
- 解析Function.prototype.bind
简介 对于一个给定的函数,创造一个绑定对象的新函数,这个函数和之前的函数功能一样,this值是它的第一个参数,其它参数,作为新的函数的给定参数. bind的作用 bind最直接的作用就是改变this的 ...
- 2.cocos2dx 3.2在语法的差异,lambada使用表达式和function和bind使用功能
1 打开 - 内置T32 Cocos2dx-3.2一个专案 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdG90b3R1enVvcXVhb ...
随机推荐
- Java之美[从菜鸟到高手演变]之智力题【史上最全】 (转)
原文地址:http://blog.csdn.net/zhangerqing/article/details/8138296 PS:在一次偶然的机会中,发现了这篇文章.希望大家能开动脑经. 智力题,每个 ...
- Struts2_使用token拦截器控制重复提交(很少用)
控制重复提交的方式:1.表单提交后页面重定向:2.Struts2.x token拦截器 大致流程: 例子: index.jsp <%@ page language="java" ...
- Linq to Sql 左连接 , 取右表可能为 null的 int类型字段
linq to sql , linq to entity 遇到一个问题, 主表, 从表 一对一 关系, 主表有记录, 从表 可能没有记录. 现在要查询 主表+从表 的某几个字段. 从表字段 有的是 ...
- 2.eclipse安装
1.进入官网https://www.eclipse.org/ 2.配置工作目录:存放 1.项目代码 2.IDE相关配置信息 3.没有配置tomcat,所以为空.
- oracle-插入到数据库中为日期
oracle中创建一个表,其中一个字段为date,当我们进行插入操作 create table xf_allsalestotal ( xf_txdate date not null, xf_store ...
- JSON:json_encode函数不能获取属性原因及解决方案
json_encode()是个解析json数据的函数,但是这个函数可以有两个参数 形式: json_decode ( string $json, ture || false ) 第一个参数传字 ...
- NO.003-2018.02.08《江城子·乙卯正月二十日夜记梦》宋代:苏轼
江城子·乙卯正月二十日夜记梦_古诗文网 江城子·乙卯正月二十日夜记梦 乙卯:公元1075年,即北宋熙宁八年. 宋代:苏轼 十年生死两茫茫,不思量,自难忘.千里孤坟,无处话凄凉.纵使相逢应不识,尘满面, ...
- Poj(1703),种类并查集
题目链接:http://poj.org/problem?id=1703 已经不是第一次接触种类并查集了,直到今天才搞懂. 感谢红黑联盟,感谢杰哥!!! 每个节点只要关系确定,不管是不是同一个集合里面, ...
- 2018.7.23 oracle中的CLOB数据类型
Oarcle中的LOB类型 1.在Oracle中,LOB(Large Object,大型对象)类型的字段现在用得越来越多了.因为这种类型的字段,容量大(最多能容纳4GB的数据),且一个表中可以有多个这 ...
- 线程 task pritce
1.使用task类创建并执行简单任务: 使用task的构造函数来创建 任务,并调用start方法来启动任务,执行异步操作 aitAll用于等待提供的所有 System.Threading.Tasks. ...