首页 > 代码库 > [c++] Callable Objects

[c++] Callable Objects

Five kinds of callable objects:

  1. Functions
  2. Pointers to functions
  3. Objects of a class that overloads ()
  4. Objects created by bind
  5. Objects created by lamdba expressions

 


1-2. Functions and Pointers to functions

    bool range5to10(int val)  // <-- bool (*p_func)(int) 改为函数指针是一个道理
{
   return (5 <= val && val <= 10);
}


vector<int> vec{ 20, 2, 4, 3, 8, 10, 15, 1}; auto presult = find_if(vec.begin(), vec.end(), range5to10); if (presult == vec.end()) { cout << "no" << endl; } else { cout << "yes" << endl; }

 

更高逼格的template,至少能在类型上更加灵活一些。

template <class T, T lb, T ub>struct range {    bool operator() (T val) {        return (lb <=val && val <=ub);    }};

auto presult = find_if(vec.begin(), vec.end(), range<int, 5, 10>{});

 

3. Object of class

class range {public:    range(int l, int u): lb(l), ub(u) {  // <-- 这里的构建函数的使用体现了其优势:初始化能多做些事情    }    bool operator() (int val) {        return (lb <=val && val <=ub);    }private:    int lb, ub;};


auto presult = find_if(vec.begin(), vec.end(), range{5, 10});

 

思考:对比模板与类两种方式,可见高大上的模板并非浪得虚名。

void f(int a, int b, int c){    cout << a << " " << b << " " << c << endl;}auto g1 = bind(f, placeholders::_1, placeholders::_2, 100);g1(1, 2); 

 

 


4. Bind

// 类的构建函数的初始化参数的一种类似的方式
class
range {public: bool operator() (int lb, int ub, int val) { return (lb <=val && val <=ub); }};auto presult = find_if(vec.begin(), vec.end(), bind(range{}, 5, 10, placeholders::_1));   //placeholders::_1 here可能代表val,暂不懂

 

When bind1st, 10绑定了greater()的第一个参数。

When bind2st, 10绑定了greater()的第二个参数。

template <class T> struct greater {  bool operator() (const T& x, const T& y) const {return x>y;}  typedef T first_argument_type;  typedef T second_argument_type;  typedef bool result_type;};

 

技术分享

Result: c1 = 5, c2 = 2;

 

 

#include<functional> 

技术分享

一眼望去,就是模板函数的样子。

 

not1(op)

not2(op)

两个要屌炸天的函数,详见链接。

 

 


5. Lambda Functions 

<functional>的本质是什么?如下:

技术分享

 

“Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。

Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。 

 

例子:(有点inline的意思)

技术分享

 

由于Lambda的类型是唯一的,不能通过类型名来显式声明对应的对象,但可以利用auto关键字和类型推导:

auto f=[](int a,int b){return a>b;};

 

** 捕获 **
auto f = [x](int a,int b){return a>x;});//x被捕获复制int x=0,y=1;auto g = [&](int x){return ++y;});//y被捕获引用,调用g后会修改y,需要注意y的生存期 (y是返回值)

** 未捕获 **bool(*fp)(int,int) = [](int a,int b){return a>b;});//不捕获时才可转换为“函数指针”

 

[c++] Callable Objects