STL学习笔记(5)- STL的函数适配器bind1st和bind2nd

原创
文章目录
  • bind1st 是将一个二元函数的第一个参数绑定为固定值的函数(实质上是仿函数类)
  • bind2nd 是将一个二元函数的第二个参数绑定为固定值的函数(实质上是仿函数类)

他们在使用的时候都需要加上头文件<functional>

1. bind1st

下面是一个关于 bind1st 的简单示例:

#include <iostream>
#include <functional>

template<typename T>
class MLess : public std::binary_function<T, T, bool>
{
public:
    bool operator() (const T& a, const T& b) const{
        return a < b;
    }
};

int main(int argc, char** argv)
{
    auto lessObj = std::bind1st(MLess<int>(), 5);
    std::cout << lessObj(6) << std::endl;
    system("pause");
    return 0;
}

这里我们先定义了一个仿函数 MLess 用来进行两个数的比较,使用函数 bind1stMLess<int>()(const T& a, const T& b) 的第一个参数绑定为5,然后传入后续的参数与5进行比较,很显然 5 < 6 的结果为 true

程序的运行结果为:
1

首先我们的自定义函数继承自类 binary_function , 关于类 binary_function 的定义很简单,源码如下:

template<class _Arg1,
    class _Arg2,
    class _Result>
    struct binary_function
    {	
    // base class for binary functions
    typedef _Arg1 first_argument_type;
    typedef _Arg2 second_argument_type;
    typedef _Result result_type;
    };

这是一个二元函数的模板类,定义两个输入参数,一个返回值。

关于 bind1st 的实现也非常简单,源码如下:

template<class _Fn2>
    class binder1st
        : public unary_function<typename _Fn2::second_argument_type,
            typename _Fn2::result_type>
    {	// functor adapter _Func(stored, right)
public:
    typedef unary_function<typename _Fn2::second_argument_type,
        typename _Fn2::result_type> _Base;
    typedef typename _Base::argument_type argument_type;
    typedef typename _Base::result_type result_type;

    binder1st(const _Fn2& _Func,
        const typename _Fn2::first_argument_type& _Left)
        : op(_Func), value(_Left)
        {    // construct from functor and left operand
        }

    result_type operator()(const argument_type& _Right) const
        {    // apply functor to operands
        return (op(value, _Right));
        }

    result_type operator()(argument_type& _Right) const
        {    // apply functor to operands
        return (op(value, _Right));
        }

protected:
    _Fn2 op;	// the functor to apply
    typename _Fn2::first_argument_type value;	// the left operand
    };

        // TEMPLATE FUNCTION bind1st
template<class _Fn2,
    class _Ty> inline
    binder1st<_Fn2> bind1st(const _Fn2& _Func, const _Ty& _Left)
    {    // return a binder1st functor adapter
    typename _Fn2::first_argument_type _Val(_Left);
    return (binder1st<_Fn2>(_Func, _Val));
    }

从代码中,可以轻松看出, bind1st 是一个函数模板,需要传入两个参数,_Func_Leftbinder1st 是一个仿函数类,构造函数中将 _Func 赋值给了成员 op_Left 赋值给我成员 value,重载的 () 正好调用的函数 op(value, _Right)

我们上面的例子中,

auto lessObj = std::bind1st(MLess<int>(), 5);

实际上是返回一个仿函数类 binder1st ,成员 opMLess<int>() 对象, value5

而调用

lessObj(6)

时,实际上是在调用函数

result_type operator()(const argument_type& _Right) const
{    // apply functor to operands
    return (op(value, _Right));
}

也就是这么调用

binder1st<MLess<int>()>(6) 
// 也就相当于执行下面这句
MLess<int>()(5, 6)

2. bind2nd

bind2nd 的内部实现跟 bind1st 类似,这里就不缀余了。下面是一个 bind2nd 的简单实用示例,将列表 nList 中的 >30 的数打印出来:

#include <iostream>
#include <functional>
#include <algorithm>
#include <list>

template<typename T>
class MTestClass : public std::binary_function<T, T, void>
{
public:
    void operator() (const T& a, const T& b) const{
        if (a > b)
            std::cout << a << std::endl;
    }
};

int main(int argc, char** argv)
{
    std::list<int> nList;
    nList.push_back(10);
    nList.push_back(20);
    nList.push_back(30);
    nList.push_back(40);
    nList.push_back(50);
    nList.push_back(60);

    std::for_each(nList.begin(), nList.end(), std::bind2nd(MTestClass<int>(), 30));
    
    system("pause");
    return 0;
}

程序的运行结果为:
40
50
60

不会飞的纸飞机
扫一扫二维码,了解我的更多动态。

下一篇文章:Qt中的信号和槽