1.C++11中function和bind的用法
2.C++模板元编程&函数柯里化初探
3.C++11中的std::function和std::bind
4.第六节 std::bind 绑定器
5.从示例到源码深入了解std::ref
C++11中function和bind的用法
在C++中,处理回调函数时,std::function和std::bind为处理可回调对象提供了便利。这两种工具分别用于封装和适应可调用对象的参数列表。std::function的用法
这个类似于C语言的函数指针,包含在头文件中。torrent 源码它支持保存普通函数、lambda表达式以及非重载的成员函数。例如:保存普通函数:std::function func;
保存lambda表达式:func = [](double a, double b) { return a + b; };
保存成员函数(需注意,不能直接保存重载的成员函数):非重载成员func = &MyClass::myMethod;
std::bind的用法
std::bind是一个通用函数适配器,允许你根据需要调整可调用对象的参数。其基本形式是:auto newCallable = std::bind(callable, arg_list); 这里的arg_list是参数列表,可以包含占位符(如_n)来表示新的可调用对象的参数位置。例如:newCallable(, _1, _2)会调用callable,将传递给第一个参数,_1和_2分别传递给后续的参数。总结
std::function提供了三种方式来存储可调用对象:普通函数、lambda和非重载成员函数。而std::bind则用于处理参数适配,特别在处理重载成员函数时必不可少。通过这些工具,你可以根据具体需求灵活传递参数。 如果你对C/C++和Linux系统开发感兴趣,棋牌超客源码特别是服务器端开发,可以点击链接深入了解:[C/C++服务器开发](服务链接)C++模板元编程&函数柯里化初探
本文非教程,仅用于记录一些想法。在担任本科生C++助教时,我了解到函数柯里化,思考如何实现自动函数柯里化。恰好之前研究过std::bind,我想到可以通过保存参数的方式实现。尝试了一种方法,但发现通过vector保存参数会增加复制开销,且参数仅能是值,不能是引用。此外,如果调用时参数个数写错,只有运行时才能发现。进一步思考后,我意识到使用lambda构造代码可以简单暴力地解决这一问题。
起初的实现仅支持int(int, int, int)类型的函数,我为此添加了一些自动适配功能,主要利用auto代替手动指定模板参数。然而,由于函数模板不支持偏特化,有符号整数源码我最终使用类模板实现。这样,看起来可以使用了,但函数参数个数仍需手动指定(Currier<4>)。为了解决这一问题,我利用R(*)(Args...)匹配函数参数,从而自动计算参数个数。
总结而言,通过上述方法,我们不仅实现了自动函数柯里化,还能根据实际需求灵活地处理不同数量的参数。尽管面临一些挑战,如增加复制开销和参数类型限制,但通过创新的实现策略,我们能够有效解决这些问题。此探索不仅加深了对C++模板元编程的理解,也为实际编程中实现自动函数柯里化提供了参考。
C++中的std::function和std::bind
C++中的std::funC++tion和std::bind一、可调用对象
可调用对象有以下几种定义:
是一个函数指针。
是一个具有operator()(运算符重载)成员函数的类对象
可被转换成函数指针的类对象
一个类成员函数指针
  C++中==可调用对象==虽然都有一个比较统一的操作形式,但是定义方法五花八门,这样就导致使用统一的sqlite vs源码使用方式保存可调用对象或者传递可调用对象时,会十分繁琐。C++中提供了std::function和std::bind统一了可调用对象的各种操作。
不同的类型可能具有相同的调用形式,如:
//?普通函数int?add(int?a,?int?b){ return?a+b;}?//?lambda表达式auto?mod?=?[](int?a,?int?b){ ?return?a?%?b;}//?函数对象类struct?divide{ int?operator()(int?denominator,?int?divisor){ return?denominator/divisor;}};上述三种可调用对象虽然类型不同,但是共享用一种调用形式:
int(int,int)std::function就可以将上述类型保存起来,如下:
std::function<int(int?,int)>?a?=?add;?std::function<int(int?,int)>?b?=?mod?;?std::function<int(int?,int)>?c?=?divide();二、std::functionstd::function是一个可调用对象包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象。它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行。
定义格式:std::function<函数类型>
std::function可以取代函数指针的作用,因为它可以延迟函数的执行,特别适合作为回调函数使用。它比普通函数更加的灵活和便利。
三、std::bind  可将std::bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。
  std::bind将可调用对象与其参数一起进行绑定,政务督查系统源码绑定后的结果可以使用std::function保存。
std::bind主要有以下两个作用:
将可调用对象和其参数绑定成一个仿函数;
只绑定部分参数,减少可调用对象传入的参数。
std::bind绑定普通函数double?my_divide(double?x,?double?y)?{ ?return?x?/?y;?}void?func1(int?b,?char?a,?long?c,?int?d){ cout?<<?b?<<?"?"?<<?a?<<?"?"?<<?c?<<?"?"?<<?d?<<?"\n";}int?main(){ auto?fn_half?=?std::bind(my_divide,?std::placeholders::_1,?2);cout?<<?fn_half()?<<?"\n";?//输出结果:?5std::function<void(int,?long)>?func?=?std::bind(func1,?std::placeholders::_1,?'c',?std::placeholders::_2,?);//输出结果:?c??func(,?);return?0;}bind的第一个参数是函数名,普通函数做实参时,会隐式转换成函数指针。因此std::bind(my_divide,std::placeholders::_1,2)等价于std::bind(&my_divide,std::placeholders::_1,2)。
std::placeholders::_1表示占位符,即对my_divide的第一个形参进行占位,将my_divide函数适配成一个形参的函数。
std::bind绑定一个成员函数struct?Foo{ void?PrintSum(int?n1,?int?n2){ cout?<<?n1?/?n2?<<?"\n";}int?data?=?;};int?main(){ Foo?foo;auto?f?=?std::bind(&Foo::PrintSum,?&foo,?,?std::placeholders::_1);//PrintSum的第二个参数占位f(5);?//输出结果:return?0;}bind绑定类成员函数时,第一个参数表示对象的成员函数的指针,第二个参数表示对象的地址。
第一个参数必须显式的指定&Foo::PrintSum,因为编译器不会将对象的成员函数隐式转换成函数指针,所以必须在Foo::PrintSum前添加&。
使用对象成员函数的指针时,必须要知道指针属于哪个对象,因此第二个参数为对象的地址&foo。
std::bind绑定一个引用参数  ==默认情况下,bind的那些不是占位符的参数被拷贝到bind返回的可调用对象中==。但是,与lambda类似,有时对有些绑定的参数希望以引用的方式传递,或是要绑定参数的类型无法拷贝。如果需要bind使用引用的方式赋值,则需要配合std::ref。
void?print(int?&a,?int?&b){ a++;b++;cout?<<?"函数调用:a="?<<?a?<<?",b?="?<<?b?<<?"\n";}int?main(){ int?a?=?1;int?b?=?2;print(a,?b);auto?func2?=?std::bind(print,?a,?std::ref(b));cout?<<?"调用前:a?=?"?<<?a?<<?",b?="?<<?b?<<?"\n";func2();cout?<<?"调用后:a?=?"?<<?a?<<?",b?="?<<?b?<<?"\n";return?0;}  调用的时候,尽管函数传入的方式都是引用,但是略有不同。参数a使用的是传统的方式,参数b采用的是std::ref的方式。输出结果进一步验证:==默认情况下,bind的那些不是占位符的参数被拷贝到bind返回的可调用对象中,即以拷贝的方式存入bind 的返回的可调用对象中。==
参考文章blogs.com/pandamohist/p/.html
版权声明:本文为CSDN博主「ufgnix」的原创文章:\ 原文链接:(/qq/article/details/)
第六节 std::bind 绑定器
std::bind 是 C++ 标准库中的一个强大工具,用于将可调用对象与其参数一起绑定,形成一个仿函数,便于稍后调用。它主要发挥两个关键作用:第一,将可调用对象与任意数量的参数绑定,形成一个仿函数;第二,将多参数可调用对象转为单参数可调用对象,仅绑定部分参数。
实际应用中,使用 std::bind 的示例代码如下:
通过 std::bind 的绑定功能,可以控制函数的执行结果,同时使用 auto fr 保存 std::bind 的返回结果,将其视为仿函数类型,直接赋值给 std::function 对象。
使用占位符如 std::placeholders::_1,代表将在函数调用时被传入的第一个参数替代。这使得 std::bind 的使用非常灵活,不仅可以直接绑定所有参数,也能仅绑定部分参数。
当仅绑定部分参数时,通过 std::placeholders 来确定空位参数属于调用时的第几个参数。随后的示例代码展示了 std::bind 的这些特性。
fr 的类型为 std::function,通过使用 std::bind,可以将 A 类成员函数 output 的指针和 a 绑定,形成一个仿函数存储于 fr 中。接着,将 A 类成员 i_ 的指针和 a 绑定,返回结果存储于 std::function 中,以备后续修改访问该成员。
通过 std::bind 和 std::function 的配合,所有可调用对象的操作方法实现了统一。接下来,将展示 std::bind 的几个实际使用案例。
1. std::bind 的简化与增强:bind 函数简化并增强了 bind1st 和 bind2nd 的功能,提供了统一的实现方式,无需分别考虑使用 bind1st 还是 bind2nd,只需使用 bind 即可。
2. 组合使用 bind 函数:bind 的强大之处还在于可以组合多个函数。以找出集合中大于5且小于的元素个数为例,首先使用 std::bind 实现判断是否大于5的功能闭包,然后实现判断是否小于的功能闭包,最后将两个闭包通过逻辑与结合,即可实现复合多个函数的功能。
从示例到源码深入了解std::ref
在编程中,std::ref是C++标准库提供的一种实用工具,用于将变量转换为可引用的对象。本文将通过实例和源码解析,深入理解std::ref的工作原理。
std::ref和std::cref的作用是生成一个std::reference_wrapper对象,它能够根据传入参数自动推导模板类型。通过这个工具,我们可以改变函数参数的传递方式,无论是引用还是值传递。
首先,让我们通过一个自定义值传递函数模板call_by_value来理解。这个模板会将参数值复制传递给fn函数。当call_by_value使用std::ref时,外部变量不会因函数内部的操作而改变,因为传递的是值拷贝。实际例子中,输出证实了这一点。
在实际编程中,如std::bind的使用,需要将引用类型参数作为引用传递,std::ref在此场合显得尤为重要。通过std::ref包装待柯里化的函数,可以实现引用的正确传递,但需要理解bind函数如何处理和存储参数值。
std::bind内部会创建一个可调用对象,其中存储参数的值。然而,对于引用类型,值传递会导致无法修改外部变量。这时,std::ref就派上用场,它通过左值引用包装变量,确保在值传递过程中仍保持引用信息。
下面以修改后的代码为例,使用std::ref包装参数。在call_by_value中,包装后的a可以成功修改,输出结果证明了引用的正确使用。同样的,std::bind示例中,通过std::ref包装a,函数调用后的变量值可以被正确修改。
总结来说,std::ref是处理引用参数和值传递问题的关键工具,通过将其应用到合适的场景,可以确保函数内部对变量的修改能正确反映到外部。