函数对象适配器主要用于对函数、函数对象进行适配(转换),使得原本不符合接口需求的函数、函数对象变得符合要求。比如:我们有一个 2 个参数的函数对象,但是我们需要 1 个参数的函数对象,此时可以通过函数对象适配器进行转换。
- 绑定适配器: bind1st、bind2nd、bind
- 成员函数适配器: mem_fun_ref、mem_fun
- 取反适配器: not1、not2
#include <iostream> #include <vector> #include <algorithm> #include <functional> using namespace std;
1. 绑定适配器
bind1st、 bind2nd 作用就是将两个参数的函数对象转换为一个参数的函数对象。
bind1st 会将某一个值赋值给第一个参数,剩下一个参数由 for_each 传递
bind2nd 会将某一个值赋值给第二个参数,剩下一个参数由 for_each 传递
绑定适配器在使用的时候,要求如下:
1. 被适配的函数对象要继承一个类:如果是两个参数函数对象需要继承:binary_function, 如果是一个参数需要继承:unary_function
2. 将重载的 operator() 函数指定为常函数
注意:bind1st、bind2nd 不能对普通函数进行适配;如果有超过两个参数的函数对象,bind1st、bind2nd 无法适配。
// binary_function<参数类型, 参数类型, 返回值类型>
struct MyFunctor : public binary_function<int, int, void>
{
void operator()(const int& v1, const int& v2) const
{
cout << v1 << " " << v2 << endl;
}
};
void test01()
{
vector<int> v = { 10, 20, 30, 40, 50 };
// 函数调用之后,会返回一个参数的函数对象,其中一个值就是固定的100
// bind1st(MyFunctor2(), 100)
for_each(v.begin(), v.end(), bind1st(MyFunctor(), 100));
for_each(v.begin(), v.end(), bind2nd(MyFunctor(), 100));
}
bind 比 bind1st 和 bind2nd 适用的场景更广,既可以适配普通函数、也可以适配函数对象,也可以适配多个参数的普通函数、函数对象。从左向右的顺序依次绑定值,不绑定的参数使用占位符代替。如下代码所示:
struct MyFunctor3
{
void operator()(const int& v1, const int& v2, const int& v3) const
{
cout << v1 << " " << v2 << " " << v3 << endl;
}
};
void print(int v1, int v2)
{
cout << v1 << " " << v2 << endl;
}
void test02()
{
// 从左向右的顺序依次绑定值,不绑定的参数使用占位符代替
auto func1 = bind(MyFunctor3(), 100, placeholders::_1, 200);
func1(1000);
auto func2 = bind(MyFunctor3(), placeholders::_1, placeholders::_2, 300);
func2(1000, 2000);
auto func3 = bind(print, placeholders::_1, 200);
func3(666);
}
2. 成员函数适配器
该适配器使用场景针对的是容器中的元素是对象引用、对象指针,通过成员函数适配器使得容器中的对象调用其成员函数。
class Person
{
public:
Person(string name, int age) : m_name(name), m_age(age) {}
void show()
{
cout << m_name << " " << m_age << endl;
}
public:
string m_name;
int m_age;
};
// mem_fun_ref、mem_fun
void test03()
{
// 容器中存储的是对象
vector<Person> v = { Person("aaa", 10),
Person("bbb", 20) ,
Person("ccc", 30) };
// 希望遍历容器中对象元素时候,调用对象的某个成员函数
// 如果容器中存储的是对象实体,那么使用 mem_fun_ref 进行成员函数适配
// 注意:成员函数不能有参数
for_each(v.begin(), v.end(), mem_fun_ref(&Person::show));
// mem_fun 用于容器中存储的是对象指针
vector<Person*> v1 = { new Person("aaa", 10),
new Person("bbb", 20) ,
new Person("ccc", 30) };
for_each(v1.begin(), v1.end(), mem_fun(&Person::show));
}
3. 取反适配器
对返回值为 bool 类型的函数对象取反操作
1. not1 针对返回值是 bool, 参数只有一个的函数对象
2. not2 针对返回值是 bool, 参数有两个的函数对象
struct MyCondition1 : public unary_function<int, bool>
{
bool operator()(const int& v) const
{
return v > 2;
}
};
void test04()
{
vector<int> v = { 9, 2, 4, 3, 1, 2, 6, 2 };
// 统计容器中元素大于 2 的个数
cout << count_if(v.begin(), v.end(), MyCondition1()) << endl;
// 统计容器中元素不大于2个数
cout << count_if(v.begin(), v.end(), not1(MyCondition1())) << endl;
vector<int> v1 = { 2, 4, 5, 6, 8, 1 };
vector<int> v2 = { 1, 3, 5, 7, 8, 1 };
// 返回两个容器中第一组不相等的元素,并返回两个迭代器
// auto it = mismatch(v1.begin(), v1.end(), v2.begin(), equal_to<int>());
// cout << *it.first << " " << *it.second << endl;
// 返回两个容器中第一组相等的元素,并返回两个迭代器
auto it = mismatch(v1.begin(), v1.end(), v2.begin(), not2(equal_to<int>()));
cout << *it.first << " " << *it.second << endl;
}

冀公网安备13050302001966号