是否有任何 C++ 运算符重载是基于其他运算符自动提供的?
Are any C++ operator overloads provided automatically based on others?
假设我正在编写一个 int
包装器并且需要提供每个运算符重载。作者必须列出每一个,还是可以根据作者提供的内容自动生成任何一个? Can/does 编译器从现有运算符中推断出任何新的自动定义运算符?
如果我定义 operator==
,它会自动给我一个 operator!=
吗?或者反之亦然?
如果我定义 operator++()
,我是否可以免费获得 operator++(int)
?或者反之亦然?
+=
类型的生意怎么样?它可以将 operator+
的现有定义与 operator=
结合起来生成 operator+=
吗?理论上应该可以,但是真的可以吗?
关于 >=
到 <
等的相同问题,或者我是否必须完整列出 >
、>
、>=
的定义, <=
?
没有
C++ 在核心语言中没有推理规则,所以即使定义说 +
它也不会假设任何关于 +=
...只是(就语言而言)完全无关。
考虑到标准库中的 <<
(左移位运算符)已被重载为表示 "output to stream"... 只是因为外观以及合理的优先级和关联性。
在核心语言中,各种运算符是独立的。有些是根据其他运算符定义的,但是如果运算符调用的重载解析失败,则不会尝试根据其他运算符来表达该调用。当需要时,程序员可以很容易地表达出来(相反,关闭这种机器可能会更困难)。
std::rel_ops
中有一组关系运算符重载可供客户端代码使用,根据 <
和 ==
定义。
您可以轻松编写一个 mixin-class,它提供 <
和 ==
或三值 compare
函数方面的关系运算符.这就是 Curiously Recurring Template Pattern, called the Barton-Nackman trick.
的最初动机
C++ 20 运算符<=>
似乎在 C++20 中,std::rel_ops
已被弃用,默认 <=>
将自动免费提供 ==, !=, <, >, <=, >=
。
改编自https://en.cppreference.com/w/cpp/language/default_comparisons:
main.cpp
#include <cassert>
#include <compare>
#include <set>
struct Point {
int x;
int y;
auto operator<=>(const Point&) const = default;
};
int main() {
Point pt1{1, 1}, pt2{1, 2};
// Just to show it Is enough for `std::set`.
std::set<Point> s;
s.insert(pt1);
// Do some checks.
assert(!(pt1 == pt2));
assert( (pt1 != pt2));
assert( (pt1 < pt2));
assert( (pt1 <= pt2));
assert(!(pt1 > pt2));
assert(!(pt1 >= pt2));
}
编译并运行:
sudo apt install g++-10
g++-10 -ggdb3 -O0 -std=c++20 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
详情请见:
在 Ubuntu 20.04、GCC 10.2.0 上测试。
C++20 添加了一项功能,允许语言为关系(<
、>
、<=
做一些事情,比如 , >=
) 和相等运算符 (==
和 !=
).
当使用相等运算符时,系统可以尝试颠倒操作数的顺序(用于不同类型的相等测试)以及取反结果以找到合适的 operator==
重载。也就是说,如果您只实现 operator==
用于 A
与 B
的相等性测试,这也将允许您对 B
与 A
进行相等性测试,以及不等式测试他们也是。
请注意,编译器不会 为您生成运算符函数。相反,它修改了调用运算符的实际位置。也就是说,它将 b != a
变成 !(a == b)
以找到合适的 ==
运算符。
对于 <=>
,它以几乎相同的方式应用于所有关系运算符(但 而非 相等运算符)。系统将根据需要将 a < b
重写为 (a <=> b) < 0
或 (b <=> a) > 0
以找到匹配的重载 <=>
运算符。
此外,您可以 = default
任何比较运算符,它按子对象方式执行,以便按顺序比较相关类型的子对象(您只能默认比较相同类型)。如果您默认使用 ==
运算符,那么根据上述规则,您也可以有效地获得 !=
。如果您默认 <=>
,您将通过重写获得所有关系运算符。
如果您默认 <=>
而没有 默认 ==
,则系统将 也 生成默认 ==
,所以默认 <=>
单独给你所有的比较运算符。
假设我正在编写一个 int
包装器并且需要提供每个运算符重载。作者必须列出每一个,还是可以根据作者提供的内容自动生成任何一个? Can/does 编译器从现有运算符中推断出任何新的自动定义运算符?
如果我定义 operator==
,它会自动给我一个 operator!=
吗?或者反之亦然?
如果我定义 operator++()
,我是否可以免费获得 operator++(int)
?或者反之亦然?
+=
类型的生意怎么样?它可以将 operator+
的现有定义与 operator=
结合起来生成 operator+=
吗?理论上应该可以,但是真的可以吗?
关于 >=
到 <
等的相同问题,或者我是否必须完整列出 >
、>
、>=
的定义, <=
?
没有
C++ 在核心语言中没有推理规则,所以即使定义说 +
它也不会假设任何关于 +=
...只是(就语言而言)完全无关。
考虑到标准库中的 <<
(左移位运算符)已被重载为表示 "output to stream"... 只是因为外观以及合理的优先级和关联性。
在核心语言中,各种运算符是独立的。有些是根据其他运算符定义的,但是如果运算符调用的重载解析失败,则不会尝试根据其他运算符来表达该调用。当需要时,程序员可以很容易地表达出来(相反,关闭这种机器可能会更困难)。
std::rel_ops
中有一组关系运算符重载可供客户端代码使用,根据 <
和 ==
定义。
您可以轻松编写一个 mixin-class,它提供 <
和 ==
或三值 compare
函数方面的关系运算符.这就是 Curiously Recurring Template Pattern, called the Barton-Nackman trick.
C++ 20 运算符<=>
似乎在 C++20 中,std::rel_ops
已被弃用,默认 <=>
将自动免费提供 ==, !=, <, >, <=, >=
。
改编自https://en.cppreference.com/w/cpp/language/default_comparisons:
main.cpp
#include <cassert>
#include <compare>
#include <set>
struct Point {
int x;
int y;
auto operator<=>(const Point&) const = default;
};
int main() {
Point pt1{1, 1}, pt2{1, 2};
// Just to show it Is enough for `std::set`.
std::set<Point> s;
s.insert(pt1);
// Do some checks.
assert(!(pt1 == pt2));
assert( (pt1 != pt2));
assert( (pt1 < pt2));
assert( (pt1 <= pt2));
assert(!(pt1 > pt2));
assert(!(pt1 >= pt2));
}
编译并运行:
sudo apt install g++-10
g++-10 -ggdb3 -O0 -std=c++20 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
详情请见:
在 Ubuntu 20.04、GCC 10.2.0 上测试。
C++20 添加了一项功能,允许语言为关系(<
、>
、<=
做一些事情,比如 , >=
) 和相等运算符 (==
和 !=
).
当使用相等运算符时,系统可以尝试颠倒操作数的顺序(用于不同类型的相等测试)以及取反结果以找到合适的 operator==
重载。也就是说,如果您只实现 operator==
用于 A
与 B
的相等性测试,这也将允许您对 B
与 A
进行相等性测试,以及不等式测试他们也是。
请注意,编译器不会 为您生成运算符函数。相反,它修改了调用运算符的实际位置。也就是说,它将 b != a
变成 !(a == b)
以找到合适的 ==
运算符。
对于 <=>
,它以几乎相同的方式应用于所有关系运算符(但 而非 相等运算符)。系统将根据需要将 a < b
重写为 (a <=> b) < 0
或 (b <=> a) > 0
以找到匹配的重载 <=>
运算符。
此外,您可以 = default
任何比较运算符,它按子对象方式执行,以便按顺序比较相关类型的子对象(您只能默认比较相同类型)。如果您默认使用 ==
运算符,那么根据上述规则,您也可以有效地获得 !=
。如果您默认 <=>
,您将通过重写获得所有关系运算符。
如果您默认 <=>
而没有 默认 ==
,则系统将 也 生成默认 ==
,所以默认 <=>
单独给你所有的比较运算符。