Объекты, допускающие только перемещение, можно передавать функциям в качестве параметров и возвращать из функций, но если вы захотите переместить содержимое std::move()
или оператором static_cast
.
Спецификатор = delete
можно задать для любой функции, а не только для копирующего конструктора и оператора присваивания. Тем самым вы ясно даете понять, что функция отсутствует. Но это еще не все — удаленная функция участвует в разрешении перегрузки, как любая другая, и вызывает ошибку компиляции, только если будет выбрана. Этим можно воспользоваться для исключения некоторых перегруженных вариантов. Например, если функция принимает параметр типа short
, то сужение типа int
можно предотвратить, написав перегруженный вариант, который принимает int
, и объявив его удаленным:
void foo(short);
void foo(int) = delete;
Любую попытку вызвать foo
с параметром типа int
компилятор встретит в штыки, так что вызывающей программе придётся явно привести параметр к типу short
:
foo(42); ←
Ошибка, перегрузка для int удалена
foo((short)42); ←
Правильно
А.3. Умалчиваемые функции
Если механизм удаленных функций позволяет явно объявить, что функция не реализована, то назначение умалчиваемых (defaulted) функций прямо противоположное - это средство указать, что компилятор должен автоматически сгенерировать реализацию функции «по умолчанию». Разумеется, это можно делать только для функций, которые компилятор и так генерирует: конструкторов, деструкторов, копирующих и перемещающих конструкторов, копирующих и перемещающих операторов присваивания.
Зачем это может понадобиться? Есть несколько причин.
•
•
•
•
•
•
Умалчиваемые функции объявляются путем добавления спецификатора = default
, например:
class Y {
private:
Y() = default; ←
Изменяем видимость
public:
Y(Y&) = default; ←
Принимаем не-const ссылку
T& operator=(const Y&) = default;←┐
объявляем умалчиваемой
│
для документирования
protected:
virtual ~Y() = default; ←
Изменяем видимость и добавляем virtual
};
Выше я упомянул, что сгенерированные компилятором функции обладают специальными свойствами, которые невозможно получить от версии, написанной пользователем. Самое существенное отличие заключается в том, что сгенерированная компилятором функция может быть
• Объекты с тривиальными копирующим конструктором, копирующим оператором присваивания и деструктором можно копировать с помощью memcpy
или memmove
.
• Литеральные типы, используемые в constexpr
-функциях (см. раздел А.4) обязаны обладать тривиальными конструктором, копирующим конструктором и деструктором.