Предоставляются ли какие-либо перегрузки операторов C++ автоматически на основе других?
Скажи я пишу int
Обертка и необходимо обеспечить перегрузку каждого оператора. Должен ли автор перечислять каждый из них, или он может автоматически генерировать что-либо на основе того, что предоставил автор? Может ли компилятор выводить какие-либо новые автоматически определенные операторы из существующих?
Если я определю operator==
это дает мне operator!=
автоматически? Или наоборот?
Если я определю operator++()
я получу operator++(int)
бесплатно? Или наоборот?
Как насчет +=
тип бизнеса? Может ли он объединить существующие определения operator+
с operator=
чтобы генерировать operator+=
? Теоретически это должно быть возможно, но так ли это?
Тот же вопрос для >=
в <
и т. д., или я должен полностью перечислить определения >
,>
,>=
,<=
?
2 ответа
В базовом языке различные операторы независимы. Некоторые из них определены в терминах других, но если не удается разрешить перегрузку для вызова оператора, то нет попытки выразить этот вызов в терминах других операторов. Когда это желательно, это может быть легко выражено программистом (наоборот, отключение такого механизма, вероятно, будет более трудным).
Существует множество перегрузок реляционных операторов в std::rel_ops
этот клиентский код может использовать, определенный в терминах<
а также==
,
Вы можете легко написать mixin-класс, который предоставляет реляционные операторы в терминах<
а также==
или с точки зрения трехзначного compare
функция. Это было первоначальной мотивацией для шаблона " Любопытно повторяющийся шаблон", названного трюком Бартона-Нэкмана.
Нет.
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
Подробнее см.: Что такое оператор <=> в C++?
Проверено на 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
любой из операторов сравнения, который выполняет подобъект-мудрый, в порядке сравнения подобъектов рассматриваемого типа (вы можете только сравнения по умолчанию того же типа). Если вы по умолчанию
==
оператор, то в соответствии с приведенными выше правилами вы фактически получаете
!=
также. Если вы по умолчанию
<=>
, вы получите все операторы отношения путем переписывания.
Если вы по умолчанию
<=>
без нарушения
==
, то система также сгенерирует значение по умолчанию
==
, поэтому по умолчанию
<=>
только дает вам все операторы сравнения.