欢迎来到皮皮网网首页

【torrent 源码】【棋牌超客源码】【有符号整数源码】std::bind 源码

来源:苏点微源码 时间:2024-11-24 11:34:29

1.C++11中function和bind的用法
2.C++模板元编程&函数柯里化初探
3.C++11中的std::function和std::bind
4.第六节 std::bind 绑定器
5.从示例到源码深入了解std::ref

std::bind 源码

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()(运算符重载)成员函数的类对象

       可被转换成函数指针的类对象

       一个类成员函数指针

       &emsp;&emsp;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::function

       std::function是一个可调用对象包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象。它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行。

       定义格式:std::function<函数类型>

       std::function可以取代函数指针的作用,因为它可以延迟函数的执行,特别适合作为回调函数使用。它比普通函数更加的灵活和便利。

三、std::bind

       &emsp;&emsp;可将std::bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。

       &emsp;&emsp;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绑定一个引用参数

       &emsp;&emsp;==默认情况下,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;}

       &emsp;&emsp;调用的时候,尽管函数传入的方式都是引用,但是略有不同。参数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是处理引用参数和值传递问题的关键工具,通过将其应用到合适的场景,可以确保函数内部对变量的修改能正确反映到外部。