C++11绑定器bind及function机制( 二 )

find_if返回指向65元素的迭代器:
file:///Users/guochen/Notes/docs/media/16656563650484/16657214749366.jpg

C++11绑定器bind及function机制

文章插图
以上就是绑定器的概念 。因此需要绑定器的原因就很明显了,绑定器可以返回一个转换后的某元函数对象 , 用于匹配泛型算法 。
根据上面的理解 , 接下来实现一下bind1st , 代码实现如下:
/*可以看到 自己实现的绑定器本质上也是个函数对象 调用operator()进行绑定*/template<typename Compare, typename T>class _mybind1st {public:_mybind1st(Compare comp, T first) : _comp(comp), _val(first) {}bool operator()(const T &second) {return _comp(_val, second);}private:Compare _comp;T _val;};/*实现bind1st 函数模板*///直接使用函数模板,好处是可以进行类型推演template<typename Compare, typename T>_mybind1st<Compare, T> mybind1st(Compare comp, const T &val) { //绑定器返回值_mybind1st为一元函数对象return _mybind1st<Compare, T>(comp, val);}上述代码中mybind1st绑定器第一个参数Compare comp是要绑定的二元函数对象,第二个参数val是在原有函数对象上绑定的值,最后绑定器调用_mybind1st模板函数对象的小括号运算符重载并返回该一元匿名函数对象,可以看到_mybind1st小括号运算符重载中已将绑定器mybind1st第二个参数val传递给了原本的二元函数对象Compare comp,因此原本绑定器接收的二元函数对象只需要处理第二个参数 。所以绑定器返回的函数对象_mybind1st其实是在原本的函数对象上套了一层参数的新的函数对象,阅读上面的代码实现 , 就可更深刻的理解bind1st的底层原理 。
与此同时 , 不难写出bind2nd的实现,顾名思义该绑定器是对第二个参数进行绑定 , 不过多赘述,贴出实现代码:
template<typename Compare, typename T>class _mybind2nd {public:_mybind2nd(Compare comp, T second) : _comp(comp), _val(second) {}bool operator()(const T &first) {return _comp(first, _val);}private:Compare _comp;T _val;};template<typename Compare, typename T>_mybind2nd<Compare, T> mybind2nd(Compare comp, const T &val) {return _mybind2nd<Compare, T>(comp, val);}根据上文,我们清楚了解到泛型算法find_if第三个参数接收一元函数对象,且该泛型算法功能是寻找第一个符合某条件的元素,我们对其补充实现,代码贴出:
/** * 自己实现了find_if后发现其实绑定器返回的就是绑定后的函数对象 * 使用绑定器的目的:就是将原本某元的函数对象转化为另一个元的函数对象 * 说白了,绑定器还是对函数对象的一个应用 **/template<typename Iterator, typename Compare>Iterator my_find_if(Iterator first, Iterator last, Compare comp) {for(; first != last; ++first) {if(comp(*first)) { //调用comp的小括号运算符重载 一元函数对象 comp.operator()(*first)return first;}}return last;}此时要寻找vector中第一个小于70的数,就可以这样写:
auto it = my_find_if(vec.begin(), vec.end(), mybind1st(greater<int>(), 70));cout << *it << endl; //打印vec中第一个小于70的数值以上 , 围绕bind1stbind2nd以及函数对象等,展开讨论了绑定器bind1stbind2nd的实现原理,但是同时我们也发现其缺点,就是只能对二元函数对象进行绑定转换,让其转换为一元函数对象,那如果遇到很多元的函数对象,我们还得一个一个自己去实现吗?所以将boost库的boost::bind引入到了C++11标准库中,接下来我们介绍C++11的绑定器std::bind , 它是对上述两种绑定器的泛化 。支持任意函数对象(其实标准库中最多支持29元函数对象 , 不过这也足够使用了) 。
补充:上面都是以函数对象为例,作为绑定器第一个参数传递 , 其实第一个参数可以是函数对象、成员函数、也可以是普通函数 。
总结:绑定器本身是函数模板,绑定器第一个参数可能是普通函数、成员函数或函数对象等,返回的一定是函数对象 。还有就是这两个绑定器在C++17中已移除,因此仅用于学习和理解绑定器 , 也方便我们对C++11引入的bind的学习 。至于当前这两个绑定器如何实现对类成员函数的绑定等等我们也没必要去寻找答案了(我一开始也在努力寻找如何使用这两个绑定器去绑定类成员函数 , 但是发现

推荐阅读