是否基于其他操作符自动提供任何c++操作符重载

Are any C++ operator overloads provided automatically based on others?

本文关键字:操作符 任何 重载 c++ 是否 于其他 其他      更新时间:2023-10-16

假设我正在编写一个int包装器,并且需要提供每个操作符重载。作者必须列出每一个单独的,或者它可以自动生成任何基于作者所提供的?编译器是否可以从现有的操作符中推断出任何新的自定义操作符?

如果我定义了operator==,它会自动给我一个operator!=吗?反之亦然?

如果我定义了operator++(),我是否可以免费获得operator++(int) ?反之亦然?

+=类型的业务呢?是否可以将现有的operator+operator=的定义结合起来生成operator+= ?从理论上讲,这应该是可能的,但事实是这样吗?

同样的问题对于>=<等,或者我必须完全列出>, >, >=, <=的定义吗?

在核心语言中,各种操作符是独立的。有些操作符是根据其他操作符定义的,但如果操作符调用的重载解析失败,则不会尝试用其他操作符表示该调用。当需要时,程序员可以很容易地表达它(相反,关闭这种机制可能会更困难)。

std::rel_ops中有一组客户端代码可以使用的关系操作符重载,它们是根据<==定义的。

可以很容易地编写一个mixin类,它根据<==或三值compare函数提供关系运算符。这就是奇怪循环模板模式的最初动机,称为Barton-Nackman技巧。

No.

c++在核心语言中没有推理规则,所以即使定义说+,它也不假设+=…它们(就语言而言)完全无关。

考虑标准库中的<<(左位移位操作符)被重载为表示"输出到流"…只是因为它的外观和合理的优先级和结合性。

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

更多细节见:What is the <=>c++中的操作符?

在Ubuntu 20.04, GCC 10.2.0上测试

c++ 20增加了一个特性,允许语言对关系运算符(<, >, <=, >=)和相等运算符(==!=)执行类似的操作。

当使用相等操作符时,系统可以尝试反转操作数的顺序(用于不同类型的相等性测试),也可以为结果取反,以找到合适的operator==过载。也就是说,如果你只实现operator==AB的相等性测试,这也将允许你对BA进行相等性测试,以及对它们进行不等性测试。

注意编译器是而不是为你生成操作符函数。而是修改调用操作符的实际位置。也就是说,为了找到合适的==运算符,它将b != a转换为!(a == b)

对于<=>,它以相同的方式应用于所有关系操作符(但不是相等操作符)。系统将根据需要将a < b重写为(a <=> b) < 0(b <=> a) > 0,以找到匹配的重载<=>操作符。

此外,您可以= default任何比较操作符,它按照子对象的顺序对所讨论的类型的子对象进行比较(您只能默认对同一类型的比较)。如果您默认使用==操作符,那么根据上述规则,您将有效地获得!=。如果默认为<=>,则可以通过重写获得所有关系操作符。

如果你默认<=> 而不默认==,那么系统也会生成一个默认的==,所以默认的<=>单独给你所有的比较运算符。