此页面中列出的具名要求,是 C++ 标准的规范性文本中使用的具名要求,用于定义标准库的期待。
某些具名要求在 C++20 中正在以概念语言特性进行形式化。在那之前,确保以满足这些要求的模板实参实例化标准库模板是程序员的重担。若不这么做,则可能导致非常复杂的编译器诊断。
全库范围的概念
建立一种顺序关系的二元谓词 (BinaryPredicate)
C++ 具名要求: Compare
比较 (Compare) 是一些标准库设施针对用户提供的函数对象类型所期待的一组要求。
对满足比较 (Compare) 的类型的对象运用函数调用操作的返回值,当按语境转换成 bool 时,若此类型所引入的严格弱序关系中,该调用的第一实参先于第二实参,则生成 true,否则生成 false。
与任何二元谓词 (BinaryPredicate) 相同,不允许该表达式的求值通过解引用的迭代器调用非 const 函数。
要求
以下情况下,类型 T
满足比较 (Compare)
- 类型
T
满足二元谓词 (BinaryPredicate) ,且
给定
T
类型的对象comp
equiv(a, b)
,为等价于!comp(a, b) && !comp(b, a)
的表达式
下列表达是必须合法且拥有其指定的效果
表达式 | 返回类型 | 要求 |
---|---|---|
comp(a, b) | 可隐式转换为 bool | 建立具有下列性质的严格弱序关系 * 对于所有 a ,comp(a,a)==false * 若 comp(a,b)==true 则 comp(b,a)==false * 若 comp(a,b)==true 且 comp(b,c)==true 则 comp(a,c)==true |
equiv(a, b) | bool | 建立具有下列性质的等价关系 * 对于所有 a ,equiv(a,a)==true * 若 equiv(a,b)==true 则 equiv(b,a)==true * 若 equiv(a,b)==true 且 equiv(b,c)==true 则 equiv(a,c)==true |
注:comp
在 equiv
所确定的等价类上引入了一种严格全序。
标准库
下列标准库设施期待比较 (Compare) 类型。
|--------------------------|------------------------------------------------------|
| set | 唯一键的集合,按照键排序 (类模板) |
| map | 键值对的集合,按照键排序,键是唯一的 (类模板) |
| multiset | 键的集合,按照键排序 (类模板) |
| multimap | 键值对的集合,按照键排序 (类模板) |
| priority_queue | 适配一个容器以提供优先级队列 (类模板) |
| sort | 将范围按升序排序 (函数模板) |
| sort | 对元素进行排序 (std::forward_list<T,Allocator>
的公开成员函数) |
| sort | 对元素进行排序 (std::list<T,Allocator>
的公开成员函数) |
| stable_sort | 将范围内的元素排序,同时保持相等的元素之间的顺序 (函数模板) |
| partial_sort | 排序一个范围的前 N 个元素 (函数模板) |
| partial_sort_copy | 对范围内的元素进行复制并部分排序 (函数模板) |
| is_sorted (C++11) | 检查范围是否已按升序排列 (函数模板) |
| is_sorted_until (C++11) | 找出最大的已排序子范围 (函数模板) |
| nth_element | 将给定的范围部分排序,确保其按给定元素划分 (函数模板) |
| lower_bound | 返回指向第一个不小于 给定值的元素的迭代器 (函数模板) |
| upper_bound | 返回指向第一个大于 给定值的元素的迭代器 (函数模板) |
| binary_search | 确定元素是否存在于某范围中 (函数模板) |
| equal_range | 返回匹配特定键值的元素范围 (函数模板) |
| merge | 归并两个已排序的范围 (函数模板) |
| merge | 合并二个已排序列表 (std::forward_list<T,Allocator>
的公开成员函数) |
| merge | 合并二个已排序列表 (std::list<T,Allocator>
的公开成员函数) |
| inplace_merge | 就地归并两个有序范围 (函数模板) |
| includes | 若一个集合是另一个的子集则返回 true (函数模板) |
| set_difference | 计算两个集合的差集 (函数模板) |
| set_intersection | 计算两个集合的交集 (函数模板) |
| set_symmetric_difference | 计算两个集合的对称差 (函数模板) |
| set_union | 计算两个集合的并集 (函数模板) |
| push_heap | 将一个元素加入到一个最大堆 (函数模板) |
| pop_heap | 从最大堆中移除最大元素 (函数模板) |
| make_heap | 从一个元素范围创建出一个最大堆 (函数模板) |
| sort_heap | 将一个最大堆变成一个按升序排序的元素范围 (函数模板) |
| is_heap | 检查给定范围是否为一个最大堆 (函数模板) |
| is_heap_until (C++11) | 查找能成为最大堆的最大子范围 (函数模板) |
| max | 返回各给定值中的较大者 (函数模板) |
| max_element | 返回范围内的最大元素 (函数模板) |
| min | 返回各给定值中的较小者 (函数模板) |
| min_element | 返回范围内的最小元素 (函数模板) |
| minmax (C++11) | 返回两个元素的较小和较大者 (函数模板) |
| minmax_element (C++11) | 返回范围内的最小元素和最大元素 (函数模板) |
| lexicographical_compare | 当一个范围按字典顺序小于另一个范围时,返回 true (函数模板) |
| next_permutation | 产生某个元素范围的按字典顺序的下一个较大的排列 (函数模板) |
| prev_permutation | 产生某个元素范围的按字典顺序的下一个较小的排列 (函数模板) |
调用示例
#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>
#include <functional>
#include <time.h>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <forward_list>
struct Cell
{
int x;
int y;
Cell() = default;
Cell(int a, int b): x(a), y(b) {}
bool operator <(const Cell &cell) const
{
if (x == cell.x)
{
return y < cell.y;
}
else
{
return x < cell.x;
}
}
};
std::ostream &operator<<(std::ostream &os, const Cell &cell)
{
os << "{" << cell.x << "," << cell.y << "}";
return os;
}
struct SCompare
{
//自定义比较函数,重载"()"操作符
bool operator()(const Cell & cell1, const Cell & cell2) const
{
return cell1 < cell2;
}
};
int main()
{
std::set<Cell, SCompare> set1;
std::map<Cell, Cell, SCompare> map1;
std::multiset<Cell, SCompare> multiset1;
std::multimap<Cell, Cell, SCompare> multimap1;
std::priority_queue<Cell, std::vector<Cell>, SCompare> priority_queue1;
auto FCompare = [](const Cell & cell1, const Cell & cell2)
{
return cell1 < cell2;
};
std::vector<Cell> vector1;
std::sort(vector1.begin(), vector1.end(), FCompare);
std::forward_list<Cell> forward_list1;
forward_list1.sort(FCompare);
std::stable_sort(vector1.begin(), vector1.end(), FCompare);
std::vector<Cell> vector2;
std::partial_sort(vector1.begin(), vector1.end(), vector2.begin(), FCompare);
std::partial_sort_copy(vector1.begin(), vector1.end(), vector2.begin(), vector2.end(), FCompare);
std::is_sorted(vector1.begin(), vector1.end(), FCompare);
std::is_sorted_until(vector1.begin(), vector1.end(), FCompare);
std::nth_element(vector1.begin(), vector1.end(), vector2.begin(), FCompare);
std::lower_bound(vector1.begin(), vector1.end(), *(vector1.begin() + 3), FCompare);
std::upper_bound(vector1.begin(), vector1.end(), *(vector1.begin() + 3), FCompare);
std::binary_search(vector1.begin(), vector1.end(), *(vector1.begin() + 3), FCompare);
std::equal_range(vector1.begin(), vector1.end(), *(vector1.begin() + 3), FCompare);
std::vector<Cell> vector3;
std::merge(vector1.begin(), vector1.end(), vector2.begin(),
vector2.end(), vector3.begin(), FCompare);
std::forward_list<Cell> forward_list2;
forward_list1.merge(forward_list2, FCompare);
std::inplace_merge(vector1.begin(), vector1.end(), vector2.begin(), FCompare);
std::includes(vector1.begin(), vector1.end(), vector2.begin(), vector2.end(), FCompare);
std::set_difference(vector1.begin(), vector1.end(), vector2.begin(),
vector2.end(), vector3.begin(), FCompare);
std::set_intersection(vector1.begin(), vector1.end(), vector2.begin(),
vector2.end(), vector3.begin(), FCompare);
std::set_symmetric_difference(vector1.begin(), vector1.end(), vector2.begin(),
vector2.end(), vector3.begin(), FCompare);
std::set_union(vector1.begin(), vector1.end(), vector2.begin(),
vector2.end(), vector3.begin(), FCompare);
std::max(Cell(), Cell(), FCompare);
std::max_element(vector1.begin(), vector1.end(), FCompare);
std::min(Cell(), Cell(), FCompare);
std::min_element(vector1.begin(), vector1.end(), FCompare);
std::minmax(Cell(), Cell(), FCompare);
std::minmax_element(vector1.begin(), vector1.end(), FCompare);
return 0;
}