Как реализовать strong exception safety push?
У меня есть класс - циклический буфер, который при push-е кладёт элемент на нужное место, при этом, если буфер полон, то он затирает один элемент и кладёт туда новый элемент, вот как реализовано у меня
void Angry_Put(size_t last_pos, const T& value, size_t new_value) {
T old_value = data_[last_pos];
data_[last_pos].~T();
try {
new (&data_[last_pos]) T(value);
} catch (...) {
new (&data_[last_pos]) T(old_value);
throw;
}
head = new_value;
}
Как бы выглядел бы код, со strong exception safety если
- Конструкторы могут кидать исключения
- Оператор копирования может кидать исключение (его может и не быть)
- Может быть такое, что объект кидает исключение через время (поэтому если допустим в начале его положили куда то, а потом вновь переложили обратно, то тут тоже может вылететь исключение)
- Важно, что тут именно, что надо придумать решение без move-семантики
Ответы (1 шт):
Автор решения: Stanislav Volodarskiy
→ Ссылка
std::swap обычно гарантирует отсутствие изменений при неуспехе. Положимся на на него:
void Angry_Put(size_t last_pos, const T& value, size_t new_value) {
using std::swap;
T copy = value;
swap(data_[last_pos], copy);
head = new_value;
}
Ещё имеет смысл перенести копирование в вызов функции:
void Angry_Put(size_t last_pos, T value, size_t new_value) {
using std::swap;
swap(data_[last_pos], value);
head = new_value;
}
P.S. Кстати сказать std::swap вводился как средство обеспечения "strong exception safety" и оптимизация задолго до появления в языке семантики перемещения.