zoukankan      html  css  js  c++  java
  • 从成员函数指针生成可调用对象:function<>、mem_fn()和bind()

    我们知道,普通函数指针是一个可调用对象,但是成员函数指针不是可调用对象。因此,如果我们想在一个保存string的vector中找到第一个空string,不能这样写:

    vector<string> svec;
    
    //...初始化
    
    auto f = &string::empty; //fp是一个成员函数指针,指向string的empty函数
    
    find_if(svec.begin(), svec.end(), fp); //错误 find_if算法需要一个可调用对象,但是fp是一个指向成员函数的指针

    这里find_if算法查找第一个具有特定大小的元素,类似find算法,find_if算法接受一个迭代器,表示一个范围,第三个参数是一个是一个谓词,find_if算法对输入序列中的每个元素调用这个指定的谓词(可调用表达式,其返回结果是一个能用作条件的值),返回第一个使谓词返回非0值的元素,如果不存在这样的元素,返回尾后迭代器。简单的说,就是从输入序列中返回第一个满足谓词的值。

    我们可以使用三种方式从指向成员函数的指针fp生成一个可调用对象:

    1.使用function生成一个可调用对象

    function<bool (const string&)> fcn = &string::empty;
    
    find_if(svec.begin(),svec.end(),fcn)

    2.使用mem_fn生成一个可调用对象

    mem_fn()把可以从成员指针生成一个可调用对象,与function不同,mem_fn可以根据成员指针的类型推断可调用对象的类型,无序用户显式地指定:

    find_if(svec.begin(), svec.end(), mem_fn(&string::empty));

    使用mem_fn(&string::empty)生成一个可调用对象,该对象接受一个string实参,返回一个bool值。

    mem_fn生成的可调用对象可以通过对象调用,也可以通过指针调用:

    auto f = mem_fn(&string::empty); //f接受一个string或者string*
    f(*svec.begin());   //传入一个string对象,f使用.*调用empty
    f(&svec[0]);        //传入一个string对象,f使用->*调用empty

    可以认为mem_fn生成的可调用对象含有一堆重载的函数调用运算符:一个接受string*,另一个接受string&。

    3.使用bind生成一个可调用对象

    auto it = find_if(svec.begin(), svec.end(), bind(&string::empty,_1));

    与mem_fn类似,bind生成的可调用对象的第一个实参既可以是string的指针,也可以是string的引用:

    auto f = bind(&string::empty,_1);
    f(*svec.begin());  //正确:实参是一个string, f使用.*调用empty
    
    f(&svec[0]);     //正确:实参是一个string的指针, f使用->*调用empty

    下面的例子来自cplusplus上mem_fn的用法:

    // mem_fn example
    #include <iostream>     // std::cout
    #include <functional>   // std::mem_fn
    
    struct int_holder {
      int value;
      int triple() {return value*3;}
    };
    
    int main () {
      int_holder five {5};
    
      // 直接调用成员函数
      std::cout << five.triple() << '
    ';   //15
    
      // 使用mem_fn调用
      auto triple = std::mem_fn (&int_holder::triple);
      std::cout << triple(five) << '
    ';   //15
     
      return 0;
    }

    参考:http://www.cplusplus.com/reference/functional/mem_fn/

         《C++ primer》

  • 相关阅读:
    输入n个整数,输出其中最小的k个
    输出单向链表中倒数第k个结点
    扑克牌大小
    Optional<T> 避免和null检查相关的bug
    筛选、切片、匹配、查找、匹配、归约
    java8 流 中的常用函数式接口
    action 和 controller 单例与多例问题
    Collections.sort Comparator.comparing 冒泡排序 效率对比
    java8 流
    将逗号分割的列,变成多列
  • 原文地址:https://www.cnblogs.com/bencai/p/9138463.html
Copyright © 2011-2022 走看看