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》

  • 相关阅读:
    HashMap按键排序和按值排序
    LeetCode 91. Decode Ways
    LeetCode 459. Repeated Substring Pattern
    JVM
    LeetCode 385. Mini Parse
    LeetCode 319. Bulb Switcher
    LeetCode 343. Integer Break
    LeetCode 397. Integer Replacement
    LeetCode 3. Longest Substring Without Repeating Characters
    linux-网络数据包抓取-tcpdump
  • 原文地址:https://www.cnblogs.com/bencai/p/9138463.html
Copyright © 2011-2022 走看看