Предоставляются ли какие-либо перегрузки операторов 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любой из операторов сравнения, который выполняет подобъект-мудрый, в порядке сравнения подобъектов рассматриваемого типа (вы можете только сравнения по умолчанию того же типа). Если вы по умолчанию == оператор, то в соответствии с приведенными выше правилами вы фактически получаете !=также. Если вы по умолчанию <=>, вы получите все операторы отношения путем переписывания.

Если вы по умолчанию <=> без нарушения ==, то система также сгенерирует значение по умолчанию ==, поэтому по умолчанию <=> только дает вам все операторы сравнения.

Другие вопросы по тегам