Генерация методов

В Ü ряд методов структур и классов может быть сгенерирован самим компилятором, нету нужны расписывать тела этих методов вручную.

К методам, которые компилятор может сгенерировать, относятся:

  • Конструкторы по умолчанию
  • Конструкторы копирования
  • Копирующие операторы присваивания
  • Деструкторы
  • Операторы сравнения на равенство (==)

Для того, чтобы какой-то метод мог быть сгенерирован, должен быть соблюдён ряд условий:

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

Но возможность генерации метода не означает, что он будет сгенерирован. Явное объявление метода всегда отменяет его генерацию. Кроме того, есть ещё ряд условий:

  • Конструктор по умолчанию будет сгенерирован, только если нету явно объявленного конструктора по умолчанию и если нету явно объявленных других конструкторов, исключая конструктор копирования.
  • Конструктор копирования и оператор присваивания будут сгенерированы только для структур. Для классов они не могут быть сгенерированы явно.
  • Оператор сравнения на равенство также по умолчанию генерируется только для структур. Также он не будет сгенерирован, если в структуре есть другие операторы ==.

А что же делать, если надо управлять генерацией методов явно? Для этого есть специальные конструкции - = delete и = default. Данные конструкции указываются вместо тела соответствующего метода при объявлении. = delete сообщает компилятору, что данный метод не надо генерировать, даже если можно. = default сообщает компилятору, что данный метод надо генерировать. Если данный метод сгенерировать не получится, будет порождена ошибка.

Примеры:

class A
{
public:
    fn constructor(i32 x) (x_= x) {}
    fn constructor()= default; // Без этого конструктор не был бы сгенерирован, т. к. есть явный конструктор кроме конструктора копирования.
    fn constructor(A& other)= default; // Без этого конструктор не был бы сгенерирован, т. к это класс.
    op=(mut this, A& other)= default; // Без этого оператор присваивания не был бы сгенерирован, т. к это класс.
    op==(A& l, A& r) : bool = default; // Без этого оператор сравнения на равенство не был бы сгенерирован, т. к это класс.

private:
    i32 x_= 0;
}

struct B
{
    fn constructor(B& other)= delete; // Без этого конструктор был бы сгенерирован, т. к это структура.
    op=(mut this, B& other)= delete; // Без этого оператор присваивания был бы сгенерирован, т. к это структура.
    op==(B& l, B& r) : bool = delete;// Без этого оператор сравнения на равенство был бы сгенерирован, т. к это структура.
    i32 x;
}