此页面中列出的具名要求,是 C++ 标准的规范性文本中使用的具名要求,用于定义标准库的期待。
某些具名要求在 C++20 中正在以概念语言特性进行形式化。在那之前,确保以满足这些要求的模板实参实例化标准库模板是程序员的重担。若不这么做,则可能导致非常复杂的编译器诊断。
函数对象 (FunctionObject) ,对于一个实参,返回一个可转换为 bool 的值而不改动实参
C++ 具名要求: Predicate
谓词 (Predicate) 要求描述了返回可作为 bool 测试的值的可调用 (Callable) 体。
谓词 (Predicate) 常与接收输入数据(单独的对象/容器)和谓词的算法一起使用,它会针对输入数据进行调用以决定进一步的动作。C++ 标准库中的一些使用谓词的例子有:
上面给出的算法设施描述是简陋的,并且有意地简要解释谓词 (Predicate) 。对于详细信息可查阅各自的页面。
换言之,若算法接收一个谓词 (Predicate) pred
和一个迭代器 first
,则它应该能经由类似 if(pred(*first)) {...} 的构造,测试迭代器 first
所指向的类型。
函数对象 pred
不应当通过解引用的迭代器运用任何非 const 函数。此函数对象可以是函数指针,或者拥有适合的函数调用运算符的类型的对象。
函数对象 (FunctionObject) ,对于两个实参,返回一个可转换为 bool 的值而不改动各实参
C++ 具名要求: BinaryPredicate
二元谓词 (BinaryPredicate) 是一些标准库设施针对用户提供的实参所期待的一组要求。
给定二元谓词 (BinaryPredicate) bin_pred
和一对迭代器 iter1
与 iter2
或一个迭代器 iter
与值 value
,表达式 bin_pred(*iter1, *iter2) 或 bin_pred(*iter, value) 必须可按语境转换为 bool。
另外,不允许表达式的求值调用解引用迭代器的非 const 成员函数。
下列标准库设施期待并非比较 (Compare) 类型的二元谓词 (BinaryPredicate) 。
unique | 删除连续的重复元素 ( std::forward_list<T,Allocator> 的公开成员函数) |
unique | 删除连续的重复元素 ( std::list<T,Allocator> 的公开成员函数) |
find_end | 在特定范围中寻找最后出现的元素序列 (函数模板) |
find_first_of | 搜索元素集合中的任意元素 (函数模板) |
adjacent_find | 查找首对相邻的相同(或满足给定谓词的)元素 (函数模板) |
mismatch | 寻找两个范围出现不同的首个位置 (函数模板) |
equal | 确定两个元素集合是否是相同的 (函数模板) |
is_permutation (C++11) | 判断一个序列是否为另一个序列的排列 (函数模板) |
search | 搜索一个元素范围 (函数模板) |
search_n | 在范围中搜索一定量的某个元素的连续副本 (函数模板) |
unique | 移除范围内的连续重复元素 (函数模板) |
unique_copy | 创建某范围的不含连续重复元素的副本 (函数模板) |
not2 (C++17 中弃用)(C++20 中移除) | 构造定制的 std::binary_negate 对象 (函数模板) |
unordered_set (C++11 起) | 唯一键的集合,按照键生成散列 (类模板) |
unordered_map (C++11 起) | 键值对的集合,按照键生成散列,键是唯一的 (类模板) |
unordered_multiset (C++11 起) | 键的集合,按照键生成散列 (类模板) |
unordered_multimap (C++11 起) | 键值对的集合,按照键生成散列 (类模板) |
?
#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>
#include <functional>
#include <time.h>
#include <vector>
struct Cell
{
int x;
int y;
Cell() = default;
Cell(int a, int b): x(a), y(b) {}
Cell &operator +=(const Cell &cell)
{
x += cell.x;
y += cell.y;
return *this;
}
Cell &operator +(const Cell &cell)
{
x += cell.x;
y += cell.y;
return *this;
}
Cell &operator *(const Cell &cell)
{
x *= cell.x;
y *= cell.y;
return *this;
}
Cell &operator ++()
{
x += 1;
y += 1;
return *this;
}
bool operator <(const Cell &cell) const
{
if (x == cell.x)
{
return y < cell.y;
}
else
{
return x < cell.x;
}
}
bool operator >(const Cell &cell) const
{
if (x == cell.x)
{
return y > cell.y;
}
else
{
return x > cell.x;
}
}
bool operator ==(const Cell &cell) const
{
return x == cell.x && y == cell.y;
}
};
std::ostream &operator<<(std::ostream &os, const Cell &cell)
{
os << "{" << cell.x << "," << cell.y << "}";
return os;
}
int main()
{
std::cout << std::boolalpha;
std::vector<Cell> vector1{{101, 102}, {103, 104}, {105, 106}, {107, 108}};
auto function1 = [](const Cell & cell)
{
if (cell > Cell{105, 106})
{
return true;
}
return false;
};
std::cout << "std::all_of( > Cell{105, 106}): "
<< std::all_of(vector1.begin(), vector1.end(), function1) << std::endl;
std::cout << "std::any_of( > Cell{105, 106}): "
<< std::any_of(vector1.begin(), vector1.end(), function1) << std::endl;
std::cout << "std::none_of( > Cell{105, 106}): "
<< std::none_of(vector1.begin(), vector1.end(), function1) << std::endl;
std::cout << std::endl;
auto function2 = [](const Cell & cell1, const Cell & cell2)
{
return cell1 == cell2;
} ;
std::vector<Cell> vector2 = vector1;
vector2.push_back({107, 108});
std::copy(vector2.cbegin(), vector2.cend(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << std::endl;
std::unique(vector2.begin(), vector2.end(), function2);
std::cout << "after unique:" << std::endl;
std::copy(vector2.cbegin(), vector2.cend(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << std::endl;
std::cout << "std::equal(vector1.begin(), vector1.end(), vector2.begin(), function2): "
<< std::equal(vector1.begin(), vector1.end(), vector2.begin(), function2);
return 0;
}
std::all_of( > Cell{105, 106}): false
std::any_of( > Cell{105, 106}): true
std::none_of( > Cell{105, 106}): false
{101,102} {103,104} {105,106} {107,108} {107,108}
after unique:
{101,102} {103,104} {105,106} {107,108} {107,108}
std::equal(vector1.begin(), vector1.end(), vector2.begin(), function2): true