一元函数对象:函数参数1个;
二元函数对象:函数参数2个;
一元谓词函数对象:函数参数1个,函数返回值是bool类型;
二元谓词函数对象:函数参数2个,函数返回值是bool类型;
之所以给返回布尔类型的函数对象专门命名,是因为谓词函数对象是用来为算法判断来服务的;
事实上,无论是普通函数指针、函数对象、lambda表达式,都是为STL中的算法服务的。
例1:顺便分析了STL中accumulate算法的源码
#include<iostream>
#include<functional>
#include<numeric>
using namespace std;
// TEMPLATE STRUCT plus
template<class _Ty = void>
struct my_plus
{ // functor for operator+
typedef _Ty first_argument_type;
typedef _Ty second_argument_type;
typedef _Ty result_type;
constexpr _Ty operator()(const _Ty& _Left, const _Ty& _Right) const
{ // apply operator+ to operands
return (_Left + _Right);
}
};
template<class _InIt,
class _Ty,
class _Fn2> inline
_Ty my_accumulate(_InIt _First, _InIt _Last, _Ty _Val, _Fn2 _Func)
{ // return sum of _Val and all in [_First, _Last), using _Func
for (; _First != _Last; ++_First)
_Val = _Func(_Val, *_First);
return (_Val);
}
// FUNCTION TEMPLATE accumulate
template<class _InIt,
class _Ty> inline
_Ty my_accumulate(_InIt _First, _InIt _Last, _Ty _Val)
{ // return sum of _Val and all in [_First, _Last)
return (my_accumulate(_First, _Last, _Val, my_plus<_Ty>()));
}
int main() {
//二元函数对象的使用
int a[] = { 1,2,3,4,5 };
const int N = sizeof(a) / sizeof(int);
cout << my_accumulate(a, a + N, 0) << endl;//15
cout << my_accumulate(a, a + N, 1, multiplies<int>()) << endl;//120
//一元函数对象的使用
//auto fp1 = negate<int>();
negate<int> fp1 = negate<int>();
cout << fp1(10) << endl;//-10
//二元谓词对象的使用
cout << equal_to<double>()(6.6, 6.6) << endl;//1
cout << greater<double>()(6.6, 6.5) << endl;//1
system("pause");
return 0;
}
例2:一元谓词函数对象的使用
#include<iostream>
#include<functional>
#include<numeric>
#include<algorithm>
using namespace std;
template <typename T>
class IsDiv
{
public:
IsDiv(const T divisor)
{
this->divisor = divisor;
}
bool operator()(T &t)
{
return (t%divisor) == 0;
}
private:
T divisor;
};
int main()
{
vector<int> v1;
for (int i = 11; i < 20; i++)
{
v1.push_back(i);
}
int divisor = 5;
vector<int>::iterator it = find_if(v1.begin(), v1.end(), IsDiv<int>(divisor));
if (it == v1.end())
{
cout << "不能被5整除" << endl;
}
else
{
cout << "第一个能被" << divisor << "整除的数:" << *it << endl;
}
system("pause");
return 0;
}
例3:
#include<iostream>
#include<functional>
#include<numeric>
#include<algorithm>
#include<vector>
using namespace std;
template<class T>
bool MyCompare(const T &a, const T &b)
{
return a < b;
}
template<class T>
void MyPrint1(const T&i)
{
cout << i << endl;
}
template<class T>
class MyPrint2 {
public:
void operator()(const T&i)
{
cout << i << endl;
}
};
int main()
{
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(rand() % 100);
}
for_each(v1.begin(), v1.end(), MyPrint1<int>);
cout << "After sorted:" << endl;
sort(v1.begin(), v1.end(), MyCompare<int>);
for_each(v1.begin(), v1.end(), MyPrint2<int>());
system("pause");
return 0;
}
例4:lambda表达式是一种可调用对象。C++中可调用对象不仅有函数指针、重载了"()"运算符的类即functor、lambda表达式。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
vector<int>vi = { 5,28,50,83,70,590,245,59,24 };
int x = 30, y = 100;
for (int&elem : vi)
{
cout << elem << " ";
}
cout << endl;
//remove_if()将所有应该移除的元素都移动到了容器尾部并返回一个分界的迭代器
vector<int>::iterator ret_it = remove_if(vi.begin(), vi.end(), [x, y](const int& n) ->bool {return x < n&&n < y; });
for (int&elem : vi)
{
cout << elem << " ";
}
cout << endl;
vi.erase(ret_it, vi.end());
//或者直接合在一起写成下面的句子:
//vi.erase(remove_if(vi.begin(), vi.end(), [x, y](int n) {return x < n&&n < y; }), vi.end());
for (int&elem : vi)
{
cout << elem << " ";
}
cout << endl;
system("pause");
return 0;
}
例5:函数适配器binder2nd的源码分析
自己已经把注释写的很清楚了,很好懂。
其实本质就是调用bind2nd函数(创建)返回一个my_binder2nd类的对象,my_binder2nd是仿函数适配器functor adapter。
#include<iostream>
#include<vector>
#include<functional>
#include<algorithm>
using namespace std;
// TEMPLATE STRUCT less
template<class _Ty = void>
struct my_less
{ // functor for operator<
typedef _Ty first_argument_type;
typedef _Ty second_argument_type;
typedef bool result_type;
constexpr bool operator()(const _Ty& _Left, const _Ty& _Right) const
{ // apply operator< to operands
return (_Left < _Right);
}
};
template<class Operation>
class my_binder2nd//仿函数适配器functor adapter
:public unary_function<typename Operation::first_argument_type, typename Operation::second_argument_type>
{
protected://两个数据成员
Operation op;//二元函数对象
typename Operation::second_argument_type value;
public:
//constructor
my_binder2nd(const Operation &obj, const typename Operation::second_argument_type &val) :op(obj), value(val) {}
typename Operation::result_type//函数返回类型
operator()(typename Operation::first_argument_type&x)const
{
return op(x, value);
}
};
template<class Operation, class T>
inline my_binder2nd<Operation>my_bind2nd(const Operation&op, const T&x)//仿函数适配器辅助函数(自己写一个my_bind2nd函数模板,目的是为了创建一个my_binder2nd的对象),主要是借助函数模板具有可以自动推导形参类型的功能
{
typedef typename Operation::second_argument_type agr2_type;
return my_binder2nd<Operation>(op, agr2_type(x));//调用my_binder2nd的constructor创建my_binder2nd的对象
}
int main()
{
vector<int>v = { 5,10,20,30,40,50 };
cout << count_if(v.begin(), v.end(), my_bind2nd(my_less<int>(), 40)) << endl;
//cout << count_if(v.begin(), v.end(), my_bind2nd(my_less<int>(), 40.1)) << endl;
system("pause");
return 0;
}