是否有基于其他人自动提供的C ++运算符重载?

时间:2015-09-28 06:26:19

标签: c++ operator-overloading compiler-generated

假设我正在编写int包装器,需要提供每个运算符的重载。作者必须列出每一个,还是可以根据作者提供的内容自动生成任何一个?编译器是否可以从现有的运算符中推断出任何新的自动定义运算符?

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

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

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

>=<等相同的问题,或者我是否必须完整列出>>>=,{{的定义1}}?

4 个答案:

答案 0 :(得分:4)

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

客户端代码可以使用std::rel_ops中的一组关系运算符重载,以<==定义。

您可以轻松编写一个mixin-class,它根据<==或三值compare函数提供关系运算符。这是Curiously Recurring Template Pattern的原始动机,称为Barton-Nackman trick

答案 1 :(得分:2)

没有

C ++在核心语言中没有推理规则,所以即使定义说+它也不会假设+= ...它们只是(如就语言而言完全不相关。

考虑到标准库中的<<(左移位运算符)已经过载,意味着“输出到流”...只是因为外观和合理的优先级和关联性。

答案 2 :(得分:0)

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 <=> operator in C++?

在Ubuntu 20.04,GCC 10.2.0上进行了测试。

答案 3 :(得分:0)

C ++ 20添加了一项功能,使该语言可以为关系(<><=,{{1} })和相等运算符(>===)。

使用相等运算符时,系统可以尝试反转操作数的顺序(用于不同类型的相等性测试),并取反结果以找到适当的!=重载。也就是说,如果您仅实现operator==来与operator==进行相等性测试A,这也将允许您对B进行相等性测试B和不相等性测试他们也是。

请注意,编译器不是为您生成运算符 functions 。相反,它正在修改调用操作员的实际位置。也就是说,它将A转换为b != a以便找到合适的!(a == b)运算符。

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

此外,您可以<=>进行子对象明智的任何比较运算符,以便对所讨论类型的子对象进行顺序比较(您只能默认相同类型的比较)。如果您默认使用= default运算符,则按照上述规则,您也可以有效地获得==。如果您默认使用!=,则可以通过重写获得所有关系运算符。

如果您默认<=> 而没有默认<=>,则系统也会 生成默认==,因此默认{仅{1}}就可以为您提供所有比较运算符。