Компиляторы С++ автоматически генерируют конструкторы копирования и операторы присваивания копий. Почему бы не swap тоже?
В наши дни предпочтительным методом реализации оператора присваивания копирования является идиома копирования и свопинга:
T& operator=(const T& other)
{
T copy(other);
swap(copy);
return *this;
}
(игнорирование формы, упрощающей копирование, которая использует значение pass-by-value).
Эта идиома имеет преимущество в транзакции перед исключениями (при условии, что реализация swap не выбрасывает). Напротив, созданный по умолчанию компилятор-оператор копирования-репликации рекурсивно выполняет копирование по всем базовым классам и членам данных и не имеет одинаковых гарантий безопасности исключений.
Между тем, внедрение методов swap вручную является утомительным и подверженным ошибкам:
- Чтобы гарантировать, что
swapне выбрасывает, он должен быть реализован для всех не-POD-элементов в классе и базовых классах, в их не-POD-элементах и т.д. - Если сопровождающий добавляет новый член данных в класс, сопровождающий должен помнить об изменении этого класса
swap. В противном случае можно ввести тонкие ошибки. Кроме того, посколькуswapявляется обычным методом, компиляторы (по крайней мере, я знаю) не выдают предупреждений, если реализацияswapнеполна.
Не было бы лучше, если бы компилятор автоматически сгенерировал методы swap? Тогда неявная реализация назначения копирования может использовать ее.
Очевидный ответ, вероятно, таков: идиома "копирование и своп" не существовала, когда С++ был разработан, и теперь это может нарушить существующий код.
Тем не менее, возможно, люди могли бы сделать выбор, чтобы компилятор сгенерировал swap с использованием того же синтаксиса, который использует С++ 0x для управления другими неявными функциями:
void swap() = default;
а затем могут быть правила:
- Если существует сгенерированный компилятором метод
swap, неявный оператор присваивания копий может быть реализован с использованием copy-and-swap. - Если не существует метода
swap, сгенерированного компилятором, неявный оператор присваивания копий будет реализован по-прежнему (вызов copy-assigment для всех базовых классов и для всех членов).
Кто-нибудь знает, были ли такие (сумасшедшие?) вещи предложены Комитету по стандартам C++, и если да, то какие члены комитета по мнениям имели?