此页面中列出的具名要求,是 C++ 标准的规范性文本中使用的具名要求,用于定义标准库的期待。
某些具名要求在 C++20 中正在以概念语言特性进行形式化。在那之前,确保以满足这些要求的模板实参实例化标准库模板是程序员的重担。若不这么做,则可能导致非常复杂的编译器诊断。
C++ 具名要求: EqualityComparable
类型必须能使用 == 运算符且结果应当具有标准语义。
以下情况下,类型 T
满足可相等比较 (EqualityComparable) :
给定
T
或 const T
类型的表达式 a
、b
与 c
下列表达式必须合法且拥有其指定的效果
表达式 | 返回类型 | 要求 |
---|---|---|
a == b | 可隐式转换为 bool | 建立一种等价关系,即满足下列性质:
|
为满足此要求,没有内建比较运算符的类型必须提供用户定义的 operator==。
对于既可相等比较 (EqualityComparable) 又可小于比较 (LessThanComparable) 的类型, C++ 标准库对相等(即表达式 a == b 的值)和等价(即表达式 !(a < b) && !(b < a) 的值)间做出区别。
C++ 具名要求: LessThanComparable
类型必须能使用 < 运算符且结果应当具有标准语义。
以下情况下,类型 T
满足LessThanComparable:
给定
T
或 const T
类型的表达式 a
、b
与 c
下列表达式必须合法并拥有其指定的效果
表达式 | 返回值 | 要求 |
---|---|---|
a < b | 可隐式转换为 bool | 建立严格弱序关系,即具有下列属性:
|
为满足此要求,没有内建比较运算符的类型必须提供用户定义的 operator<。
对于既可相等比较 (EqualityComparable) 又可小于比较 (LessThanComparable) 的类型,C++ 标准库在相等(即表达式 a == b 的值)和等价(即表达式 !(a < b) && !(b < a) 的值)间做出区别。
C++ 具名要求: NullablePointer (C++11 起)
指定该类型是能与 std::nullptr_t 对象进行比较的指针式类型。
类型必须满足所有下列要求:
此外,此类型的一个值初始化的对象必须产生该类型的空值(null)。空值必须仅与自身等价。该类型的默认初始化可拥有不确定值。
此类型必须可按语境转换成 bool。若其值等价于其空值则此转换的效果为 false,否则为 true。
此类型进行的操作均不可抛异常。
此类型必须满足下列额外的表达式,给定该类型的两个值 p
与 q
,以及 np
是 std::nullptr_t 类型的值(可有 const 限定):
表达式 | 效果 |
Type p(np); Type p = np; | 之后 p 等价于 nullptr。 |
Type(np) | 等价于 nullptr 的临时对象。 |
p = np | 必须返回 Type& ,而且之后 p 等价于 nullptr。 |
p != q | 必须返回能按语境转换成 bool 的值。效果为 !(p == q) 。 |
p == np np == p | 必须返回能按语境转换成 bool 的值。效果为 (p == Type()) 。 |
p != np np != p | 必须返回能按语境转换成 bool 的值。效果为 !(p == np) 。 |
注意,对可空指针 (NullablePointer) 类型不要求解引用(operator*
或 operator->
)。满足这些要求的最小化类型是
class handle
{
int id;
public:
handle(std::nullptr_t = nullptr) : id(0) { }
explicit operator bool()
{
return id != 0;
}
friend bool operator ==(handle l, handle r)
{
return l.id == r.id;
}
friend bool operator !=(handle l, handle r)
{
return !(l == r);
}
};
下列类型必须满足可空指针 (NullablePointer) :
X
的成员类型 X::pointer
、X::const_pointer
、X::void_pointer
及 X::const_void_pointer
X::pointer
#include <iostream>
#include <string>
#include <iomanip>
#include <complex>
#include <tuple>
#include <typeinfo>
struct Cell
{
int x;
int y;
Cell() = default;
Cell(int a, int b): x(a), y(b) {}
//类型必须能使用 == 运算符且结果应当具有标准语义。
bool operator ==(const Cell &cell) const
{
return x == cell.x && y == cell.y;
}
bool operator !=(const Cell &cell) const
{
// return x != cell.x && y != cell.y;
return !(*this == cell);
}
//类型必须能使用 < 运算符且结果应当具有标准语义。
bool operator <(const Cell &cell) const
{
if (x < cell.x)
{
return true;
}
return y < cell.y;
}
};
class handle
{
int id;
public:
handle(std::nullptr_t = nullptr) : id(0) { }
explicit operator bool()
{
return id != 0;
}
friend bool operator ==(handle l, handle r)
{
return l.id == r.id;
}
friend bool operator !=(handle l, handle r)
{
return !(l == r);
}
};
std::ostream &operator<<(std::ostream &os, const Cell &cell)
{
os << "{" << cell.x << "," << cell.y << "}";
return os;
}
int main()
{
std::cout << std::boolalpha;
Cell cell1 = {101, 102};
Cell cell2 = {101, 102};
Cell cell3 = {201, 202};
std::cout << cell1 << " == " << cell2 << " : "
<< (cell1 == cell2) << std::endl;
std::cout << cell1 << " != " << cell2 << " : "
<< (cell1 != cell2) << std::endl;
std::cout << cell1 << " == " << cell3 << " : "
<< (cell1 == cell3) << std::endl;
std::cout << cell1 << " != " << cell3 << " : "
<< (cell1 != cell3) << std::endl;
std::cout << cell1 << " < " << cell2 << " : "
<< (cell1 < cell2) << std::endl;
std::cout << "!(" << cell1 << " < " << cell2 << ") : "
<< !(cell1 < cell2) << std::endl;
std::cout << cell1 << " < " << cell3 << " : "
<< (cell1 < cell3) << std::endl;
std::cout << "!(" << cell1 << " < " << cell3 << ") : "
<< !(cell1 < cell3) << std::endl;
return 0;
}
{101,102} == {101,102} : true
{101,102} != {101,102} : false
{101,102} == {201,202} : false
{101,102} != {201,202} : true
{101,102} < {101,102} : false
!({101,102} < {101,102}) : true
{101,102} < {201,202} : true
!({101,102} < {201,202}) : false