C++ std::bind

C++11的std::bind是个巨大的进步,把各种稀奇古怪的函数对象统一起来。古老的bind1st终于退出历史舞台。但是bind仍旧存在漏洞。例如:

#include <iostream>
#include <cmath>
#include <functional>   // std::bind
using namespace std::placeholders;    // adds visibility of _1, _2, _3,...

double bevel(double a, double b){
    std::cout << "bevel called" << std::endl;
    return std::sqrt(a*a+b*b);
}

double add(double a, double b){
    std::cout << "add called" << std::endl;
    return a+b;
}

int main(){
    auto fun  = std::bind( bevel, add(1,2),   _1 ); //一个callable
    fun(4);  //调用fun,结果是5
}

调用std::bind函数时,需要对add(1,2)这个子表达式求值,如果想“延迟”求值,只能这么做:

 1 #include <iostream>
 2 #include<cmath>
 3 #include <functional>   // std::bind
 4 using namespace std::placeholders;    // adds visibility of _1, _2, _3,...
 5 
 6 double bevel(double a, double b){
 7     std::cout << "bevel called" << std::endl;
 8     return std::sqrt(a*a+b*b);
 9 }
10 
11 double add(double a, double b){
12     std::cout << "add called" << std::endl;
13     return a+b;
14 }
15 
16 int main()
17 {
18     auto fun = std::bind( bevel, std::bind(add,1,2), _1 );
19     std::cout << "now fun call" << std::endl;
20     fun(4);21 }

第18行嵌套一个bind就把人搞晕。嵌套的bind(add,1,2)不会立刻调用add,只会返回一个callable对象,传递给外层的bind。

当调用第20行时,实际上就是调用了bevel( someCallableObj(), 4 ); someCallableObj()调用add(1,2),因此延迟调用实现。

C++14开始出现的lambda表达式,让明察的洞见穿透了这些隐晦的角落,改造后的代码如下:

//... as before

int main()
{
    auto funL = [](double b){
        return bevel( add(1,2) , b );
    };
    std::cout << "now funL call\n";
    funL(4);

    return 0;
}

根据Effective Modern C++的作者之言,如果还看不到lambda表达式的好处,那简直和瞎子没什么两样。

下面再感受一下时代的变迁:

#include <functional>
#include <algorithm>
using namespace std;
int main () {
    int numbers[] = {10,20,30,40,50,10};
    int cx = count_if (numbers, numbers+6, bind1st(equal_to<int>(),10) );
}

C++03 要根据参数类型选函数bind1st(逆向思维,相当费脑)

#include <functional>
#include <algorithm>
using namespace std;
using namespace std::placeholders;
int main () {
    int numbers[] = {10,20,30,40,50,10};
    int cx = count_if (numbers, numbers+6, bind(equal_to<int>(),10,_1) );
}

C++11 终于把函数先定下来就是一个std::bind, 然后选各项参数,callable对象,值参数,占位符参数。终于思维正常了。

#include <algorithm>
using namespace std;
int main () {
    int numbers[] = {10,20,30,40,50,10};
    int cx = count_if (numbers, numbers+6, [](int i){ return i==0; } );
}

C++17 的lambda。不再需要什么_1,_2,_3。。。占位符能弄晕很多人。直白的代码逻辑。

原文链接: https://www.cnblogs.com/thomas76/p/8642088.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    C++ std::bind

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/397534

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月11日 上午9:14
下一篇 2023年4月11日 上午9:14

相关推荐