仿函数是什么?仿函数什么时候必须继承一元或者二元谓词

什么是仿函数?为什么有些仿函数必须要继承unary_function或者binary_function

仿函数的概念

使用起来像函数一样的东西,实际是一个对象
主要功能是为了搭配STL的算法,也将成为用于改变容器的默认行为,比如set中使用less<>默认排序,可以传入greater等仿函数改变默认行为
跟STL算法之间的关系图:
在这里插入图片描述
仿函数必须定义operator(),下面是一个小示例

template<typename T>
struct myPlus
{
	T operator()(const T& a1, const T& a2) const { return a1 + a2; }

};
void test05()
{
	myPlus<int> pob;
	cout << pob(5, 9) << endl;
	cout << myPlus<int>()(7, 8) <<endl;
}

STL中的plus仿函数的实现(vs中参看的源码)

template<class _Ty = void>
	struct plus
	{	// functor for operator+
	_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty first_argument_type;
	_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty second_argument_type;
	_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty result_type;

	constexpr _Ty operator()(const _Ty& _Left, const _Ty& _Right) const
		{	// apply operator+ to operands
		return (_Left + _Right);
		}
	};

仿函数适配器

下面有用到bind,简单介绍下仿函数适配器。
仿函数适配器目的在于将无法匹配的仿函数函数,匹配成可以匹配的型别。
比如bind1st bind2nd mem_fun等

可配接的仿函数

STL定义了两个Class,unary_function和binary_function ,继承其中一个,就拥有了其中的型别,这时候就是可以配接了。以下摘是VS的源码

template<class _Arg,
	class _Result>
	struct unary_function
	{	// base class for unary functions
	typedef _Arg argument_type;
	typedef _Result result_type;
	};

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;
	};

仔细观察就发现这两个类其实没有任何member,只有一些型别,那么作用呢?

什么时候必须定义可配接的仿函数

初学时候有疑惑为什么有些不继承上面两个类的仿函数仍然能够用于算法,那到底什么时候必须定义呢?

template<typename T>
struct MyGreater:public binary_function<T, T, T>
{
	T operator()(const T& a1, const T& a2)const { return a1 > a2; }
};
void test06()
{
	vector<int> v = { 23, 96, 4, 5 };
	vector<int>::iterator pos = find_if(v.begin(), v.end(), bind2nd(MyGreater<int>(), 23));
	if (pos != v.end())
	{
		cout << *pos << endl;
	}
}

如上代码就必须继承binary_function!
原因在于如下bind2nd的源码如下:

template<class _Fn,
	class _Ty>
	_NODISCARD inline binder2nd<_Fn> bind2nd(const _Fn& _Func, const _Ty& _Right)
	{	// return a binder2nd functor adapter
	typename _Fn::second_argument_type _Val(_Right);
	return (binder2nd<_Fn>(_Func, _Val));
	}

注意到了没有,用到了型别 _Fn::second_argument_type,如果不继承binary_function你就没法获取到这个型别,特别当某些仿函数你使用的是库函数,而不是自己定义的函数。
综上,STL仿函数应该具备函数适配器(配接器)使用的能力,才能更好的用于算法

©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页