【C++】STL 算法 ⑩ ( 函数适配器 | 函数适配器概念 | 函数适配器分类 | 函数适配器辅助函数 | std::bind2nd 函数原型及示例 | std::bind 函数原型及示例 )

C/C++
200
0
0
2024-03-31

一、函数适配器简介

1、函数适配器概念

在 STL 中 预定义了很多 函数对象 , 如果要 对 函数对象 的 参数 / 返回值 进行 计算 或 设置 , 可以 使用 " 函数适配器 " 实现上述需求 ;

" 函数适配器 " 可以 将 已存在的 函数对象 转化为 另一种符合要求的 函数对象 ;

" 函数适配器 " 定义在 <functional> 头文件 中 ;

2、函数适配器分类

" 函数适配器 " 常用类型的两类 :

  • 绑定适配器 :std::bind 绑定适配器 : 引入的一个 通用绑定机制 , 可 绑定 函数 / 函数指针 / 函数对象 / 成员函数指针 任意 位置 的 参数 到指定的值 , 也可以重新排列参数的顺序 , 或者将多个可调用对象组合在一起 ; C++ 11 最新引入的 , 建议使用 该 绑定适配器 ;
  • std::binder1st 绑定适配器 : 将一个二元函数对象的 第一个 参数 绑定到一个特定的值 , 从而创建一个新的一元函数对象 ; C++ 11 弃用 , 建议使用 std::bind 绑定适配器 ;
  • std::binder2nd 绑定适配器 : 将一个二元函数对象的 第二个 参数 绑定到一个特定的值 , 从而创建一个新的一元函数对象 ; C++ 11 弃用 , 建议使用 std::bind 绑定适配器 ;
  • 组合适配器 :unary_negate 组合适配器 : 将 一元谓词 的返回值 , 进行 逻辑取反 操作 , 得到一个新的 bool 类型 布尔值 ;
  • binary_negate 组合适配器 : 将 二元谓词 的返回值 , 进行 逻辑取反 操作 , 得到一个新的 bool 类型 布尔值 ;

3、函数适配器辅助函数

函数适配器 的 创建构造 需要很复杂的类型声明 , 为了方便开发 , C++ 的 STL 标准模板库 中提供了 " 函数适配器辅助函数 " , 可以 无需显示声明类型 , 就可以 实现 函数适配器 的创建 ;

常用的 " 函数适配器辅助函数 " :

  • bind1st 函数 : 辅助构造 std::binder1st 绑定适配器 实例对象 , 可以 为 二元函数 第一个参数 绑定一个固定的值 ;
  • bind2nd 函数 : 辅助构造 std::binder2nd 绑定适配器 实例对象 , 可以 为 二元函数 第二个参数 绑定一个固定的值 ;
  • not1 函数 : 辅助构造 unary_negate 组合适配器 实例对象 , 将 一元谓词 的返回值 , 进行 逻辑取反 操作 ;
  • not2 函数 : 辅助构造 unary_negate 组合适配器 实例对象 , 将 二元谓词 的返回值 , 进行 逻辑取反 操作 ;

二、函数适配器使用示例 - std::bind2nd 函数

1、std::bind2nd 函数原型

std::bind2nd 是一个函数适配器 , 它用于 生成一个新的一元函数对象 , 该对象将给定二元函数对象的第二个参数绑定到一个特定的值 ;

std::bind2nd 函数原型如下 :

template <class Operation>  
binder2nd<Operation> bind2nd(const Operation& op, const typename Operation::second_argument_type& value);
  • 参数解析 :
  • Operation &op 参数 : 该参数是 要绑定的二元函数对象 , 它必须定义 second_argument_type 作为其第二个参数的类型 , 也就是说 第二个参数类型 需要 与 本函数的 value 值类型相同 ;
  • value 参数 : 该参数是 要绑定到二元函数对象第二个参数的 值 或 变量 ;
  • 返回值解析 : 返回一个 binder2nd 类 的对象 , 该对象是一个一元函数对象 , 可以像普通函数对象一样被调用 ;

2、代码示例 - std::bind2nd 函数

代码示例 :

#include "iostream"
using namespace std;
#include <vector>
#include <algorithm>
#include "functional"

int main() {

	// 创建一个 set 集合容器
	vector<int> myVector;

	// 向容器中插入元素
	myVector.push_back(9);
	myVector.push_back(5);
	myVector.push_back(2);
	myVector.push_back(7);
	myVector.push_back(2);

	// 向 foreach 循环中传入 Lambda 表达式
	for_each(myVector.begin(), myVector.end(), [](int a) {
		std::cout << a << " ";
		});
	cout << endl;

	// 计算 vector 容器中 , 值为 2 的个数
	int equal_num = 2;
	int count = count_if(myVector.begin(), myVector.end(), bind2nd(equal_to<int>(), equal_num));
	cout << "值为 2 的元素个数 : " << count << endl;

	
	// 控制台暂停 , 按任意键继续向后执行
	system("pause");
	return 0;
};

执行结果 :

9 5 2 7 2
值为 2 的元素个数 : 2
Press any key to continue . . .

在这里插入图片描述

三、函数适配器使用示例 - std::bind 函数

1、std::bind 函数原型

std::bind 函数适配器 是 C++11 新引入的 函数适配器 , 可以 将 函数 / 函数对象 / 函数指针 与 其参数绑定到一起 , 产生一个新的可调用函数对象 ;

std::bind 函数适配器 比 std::bind1st 和 std::bind2nd 函数适配器更加灵活 ,

  • std::bind1st 函数适配器 只能绑定 函数对象 第一个函数参数 ;
  • std::bind2nd 函数适配器 只能绑定 函数对象 第二个函数参数 ;
  • std::bind 函数适配器 不仅能绑定 第一第二个函数参数 , 还能绑定第三个第四个直至第 N 个函数参数 , 没有任何位置限制 ;

std::bind 函数原型如下 :

template< class Fn, class... Args >  
/*unspecified*/ bind( Fn&& fn, Args&&... args );
  • 参数解析 :
  • Fn&& fn 参数 : fn 是一个可调用对象 , 可以是 函数 / 函数指针 / 成员函数 / 成员函数指针 / 函数对象 / 谓词 等可调用对象 ;
  • Args&&… args 参数 : 这是一个可变的参数 , 参数可以是值 , 引用 或者 占位符 ;
  • 返回值解析 : 返回的是一个未指定的类型 , 这个类型是一个函数对象 , 可以像普通函数那样被调用 ; 当返回的函数对象被调用时 , 它会用提供的参数和 std::bind 中的占位符来调用 fn ;

占位符 是 std::placeholders::_1 , std::placeholders::_2 等值 ;

如果 参数中是 std::placeholders::_1 占位符 , 表示 第一个 参数 , 不进行修改 , 仍然保持其默认值 ; std::placeholders::_2 占位符 , 表示 第二个 参数 , 不进行修改 , 仍然保持其默认值 ;

2、代码示例 - std::bind 函数

代码示例 :

#include "iostream"
using namespace std;
#include <vector>
#include <algorithm>
#include "functional"

int main() {

	// 创建一个 set 集合容器
	vector<int> myVector;

	// 向容器中插入元素
	myVector.push_back(9);
	myVector.push_back(5);
	myVector.push_back(2);
	myVector.push_back(7);
	myVector.push_back(2);

	// 向 foreach 循环中传入 Lambda 表达式
	for_each(myVector.begin(), myVector.end(), [](int a) {
		std::cout << a << " ";
		});
	cout << endl;

	// 计算 vector 容器中 , 值为 2 的个数
	int equal_num = 2;
	int count = count_if(myVector.begin(), myVector.end(), bind(equal_to<int>(), placeholders::_1, equal_num));
	cout << "值为 2 的元素个数 : " << count << endl;

	
	// 控制台暂停 , 按任意键继续向后执行
	system("pause");
	return 0;
};

执行结果 :

9 5 2 7 2
值为 2 的元素个数 : 2
Press any key to continue . . .

在这里插入图片描述