一、函数适配器示例 - 函数适配器正常用法
1、modulus 函数对象 - 取模运算
在 <functional> 头文件 中 , 预定义了 modulus 函数对象 , 这是一个 二元函数对象 , 在该函数对象类中 , 重写了 函数调用操作符 函数 operator() , 该 预定义函数对象 代码如下 :
代码语言:javascript复制// STRUCT TEMPLATE modulus
template <class _Ty = void>
struct modulus {
_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 {
return _Left % _Right;
}
};
该函数对象 定义了 模板参数 template <class _Ty = void> , _Ty 泛型的默认参数是 void , 即 如果 不指定 模板参数 , _Ty 泛型就是 void 类型 , 一般情况下使用 int 类型 进行取模运算 ;
在 modulus 函数对象 中 , 重载 函数调用操作符 函数 是最核心的函数 , 在该函数中 , 将第一个参数 const _Ty& _Left 与 第二个参数 const _Ty& _Right 进行取模运算 , 返回 模运算 的结果 ;
代码示例 :
代码语言:javascript复制#include "iostream"
using namespace std;
#include "functional"
int main() {
// 创建函数对象
modulus<int> mod;
// 调用函数对象
int result = mod(5, 2);
// 打印执行结果
cout << "result = " << result << endl;
// 控制台暂停 , 按任意键继续向后执行
system("pause");
return 0;
};
执行结果 :
2、std::count_if 函数原型
std::count_if 函数 是 C 标准库算法 , 该 函数 的作用是 计算范围内满足特定条件的元素的数量 , 该函数 接受 一个迭代器范围 和 谓词函数 ;
注意 : 迭代器范围 的 起始迭代器 ~ 终止迭代器 是一个 前闭后开区间
std::count_if 算法的 函数原型 如下 :
代码语言:javascript复制// FUNCTION TEMPLATE count_if
template <class _InIt, class _Pr>
_NODISCARD _Iter_diff_t<_InIt> count_if(_InIt _First, _InIt _Last, _Pr _Pred) { // count elements satisfying _Pred
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
_Iter_diff_t<_InIt> _Count = 0;
for (; _UFirst != _ULast; _UFirst) {
if (_Pred(*_UFirst)) {
_Count;
}
}
return _Count;
}
- _InIt _First 参数 : 迭代器范围的 起始迭代器 , 包括本迭代器指向的元素 ;
- _InIt _Last 参数 : 迭代器范围的 终止迭代器 , 不包括本迭代器指向的元素 ;
- _Pr _Pred 参数 : 谓词函数 ;
3、代码示例 - 使用 函数适配器 绑定函数对象参数
在下面的代码中 , 将 myVector 单端数组 容器 中的元素 设置给 modulus 函数对象的 第一个参数 , 将 equal_num 变量设置为 该 modulus 函数对象的 第二个参数 , 然后依次遍历 myVector 单端数组 容器 将每个元素 与 equal_num 进行取模运算 ;
代码语言:javascript复制 // 计算 vector 容器中 , 值为 2 的个数
int equal_num = 2;
// 取模运算 , 模 2 返回值 1 就是奇数 , 返回值 0 就是偶数
int count = count_if(myVector.begin(), myVector.end(), bind2nd(modulus<int>(), 2));
代码示例 :
代码语言:javascript复制#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;
// 取模运算 , 模 2 返回值 1 就是奇数 , 返回值 0 就是偶数
int count = count_if(myVector.begin(), myVector.end(), bind2nd(modulus<int>(), 2));
cout << "值奇数元素个数 : " << count << endl;
// 控制台暂停 , 按任意键继续向后执行
system("pause");
return 0;
};
二、函数适配器示例 - 函数适配器嵌套用法
1、std::not1 函数原型
std::not1 是 预定义的 函数适配器 函数 , 该 函数 接收一个 一员函数对象 , 返回新的 一元函数对象 , 返回的 一元函数对象 是对输入的 一元函数对象 的 结果 进行 逻辑非 运算 ;
std::not1 函数原型如下 :
代码语言:javascript复制template <class UnaryPredicate>
unary_negate<UnaryPredicate> not1(UnaryPredicate pred);
- UnaryPredicate pred 参数 : 一元谓词 , 也就是 接受单个参数 并返回布尔值的可调用对象 ;
- unary_negate<UnaryPredicate> 类型返回值 : 返回值 是 封装了 UnaryPredicate 并提供了一个 operator() 成员函数 的 一元谓词 , 该函数对 UnaryPredicate 的结果取反 ;
std::not1 可以 与 std::bind1st 或 std::bind2nd 嵌套使用 , 创建更复杂的谓词 ;
2、代码示例 - 函数适配器嵌套用法
核心代码如下 :
代码语言:javascript复制 // 计算 vector 容器中 , 值为 2 的个数
int equal_num = 2;
// 取模运算 , 模 2 返回值 1 就是奇数 , 返回值 0 就是偶数
// not1 将其取反 也就是获取的是 非奇数 个数
int count = count_if(myVector.begin(), myVector.end(), not1(bind2nd(modulus<int>(), 2)));
下面的代码中 , modulus 是一个二元函数对象 , 返回 0 或 1 可以当做 二元谓词 ;
bind2nd(modulus<int>(), 2) 将 二元谓词 中的 第二个元素进行了绑定 , 只需要接收一个参数 , 变成了 一元谓词 ;
not1(bind2nd(modulus<int>(), 2)) 将 上述 一元谓词 取反 , 得到一个新的一元谓词 ;
代码示例 :
代码语言:javascript复制#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;
// 取模运算 , 模 2 返回值 1 就是奇数 , 返回值 0 就是偶数
// not1 将其取反 也就是获取的是 非奇数 个数
int count = count_if(myVector.begin(), myVector.end(), not1(bind2nd(modulus<int>(), 2)));
cout << "偶数元素个数 : " << count << endl;
// 控制台暂停 , 按任意键继续向后执行
system("pause");
return 0;
};
执行结果 :
代码语言:javascript复制9 5 2 7 2
偶数元素个数 : 2
请按任意键继续. . .