Перегрузка операторов

Для типов структур и классов возможно перегрузить ряд операторов и операций. Перегруженный оператор это просто функция внутри класса и структуры, имеющая специальное имя и выполняющая ряд требований. У всех перегруженных операторов и операций тип одного из аргументов должен быть той структуры или того класса, в которой объявлены операция или оператор.

Объявляется перегруженный оператор с использованием ключевого слова op и имени оператора после него.

struct Int
{
    i32 x;

    op+( Int& l, Int& r ) : Int // Перегруженный бинарный оператор
    {
        var Int i{ .x= l.x + r.x };
        return i;
    }

    op-( Int& a ) : Int // Перегруженный префиксный унарный оператор
    {
        var Int b{ .x= -a.x };
        return b;
    }

    op++( mut this ) // Перегруженная унарная операция
    {
        ++x;
    }

    op[]( this, i32 y ) : i32 // Перегруженный постфиксный оператор
    {
        return x * y;
    }
}

fn Foo()
{
    var Int mut a{ .x= 42 }, b{ .x= 666 };
    ++a;
    auto ab= a + b;
    auto minus_b= -b;
    var i32 r= a[5];
}

Перегружаемые операторы и операции:

Оператор

тип

Число аргументов

Возвращаемый результат

-

префиксный оператор

1

любой

!

префиксный оператор

1

любой

~

префиксный оператор

1

любой

+

бинарный оператор

2

любой

-

бинарный оператор

2

любой

*

бинарный оператор

2

любой

/

бинарный оператор

2

любой

%

бинарный оператор

2

любой

&

бинарный оператор

2

любой

|

бинарный оператор

2

любой

^

бинарный оператор

2

любой

>>

бинарный оператор

2

любой

<<

бинарный оператор

2

любой

==

бинарный оператор

2

bool

<=>

бинарный оператор

2

i32

[]

постфиксный оператор

2

любой

()

постфиксный оператор

1 и более

любой

++

унарная операция

1

void

--

унарная операция

1

void

=

бинарная операция

2

void

+=

бинарная операция

2

void

-=

бинарная операция

2

void

*=

бинарная операция

2

void

/=

бинарная операция

2

void

%=

бинарная операция

2

void

&=

бинарная операция

2

void

|=

бинарная операция

2

void

^=

бинарная операция

2

void

<<=

бинарная операция

2

void

>>=

бинарная операция

2

void

Ряд перегруженных операторов вызываются особым образом.

Для == и != вызывается перегруженный оператор ==. Не существует отдельной перегрузки оператора !=. Для получения результата != результат вызова == инвертируется.

Для операторов упорядочивающего сравнения (<, <=, >, >=) вызывается перегруженный оператор <=>. Результат его вызова сравнивается с нулём для получения конечного результата. Перегруженному оператору <=> не обязательно возвращать строго -1 или +1 для индикации отношения больше/меньше, важен лишь знак результата.

Постфиксные операторы

Особое место занимают постфиксные операторы. У всех них есть требование, чтобы тип первого аргумента был тот же, что у типа структуры или класса, где объявлен этот оператор.

Оператор индексирования [] позволяет обращаться по индексу к структуре или классу, как будто это массив. При этом тип индекса может быть любым. Это позволяет, например, организовать ассоциативные контейнеры с доступом по ключу с использованием данного оператора.

Оператор вызова () позволяет обращаться с структурой или классом подобно функции. Это позволяет, например, реализовывать функциональные объекты.