Политика исключений для «наконец-то» в переполнении стека

Рассмотрим класс finallyработает произвольный пользовательский код в деструкторе.

Вот самая минимальная реализация (без пересылки, вспомогательной функции и т. Д.):

template<typename Func>
class finally
{
public:
finally(Func f) : f_(f) {}
~finally() { f_(); }

private:
Func f_;
};

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

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

1) Ничего не делать. ~finally() /*noexcept*/ { f_(); }

Разрушитель finally неявно noexceptпоэтому любое исключение в коде пользователя приводит к terminate(),
Пользователь должен каждый раз думать об отсутствии исключений в своем коде и защищать его вручную с помощью try / catch, если он выбрасывает.

2) Полностью прозрачный деструктор. ~finally() noexcept(f_()) { f_(); }

Разрушитель finally условно noexceptпоэтому любое исключение передается и terminate() вызывается, только если это происходит во время разматывания стека.
Пользователь, вероятно, должен подумать о сценариях раскрутки стека, но terminate() в таких ситуациях может быть правильным решением по умолчанию.

3) Поймай все исключения в деструкторе. ~finally() { try { f_(); } catch (...) {} }

Классический деструктор ничего не бросает.
Ограничивает возможности пользователя по проверке ошибок с исключениями, но с хорошим намерением. Вероятно, менее эффективный из-за блока try / catch. Пользователь не должен думать ни о чем.

3+) (Вероятно) оптимизирован 3), использует специализацию / SFINAE, чтобы опустить блок try / catch, если f_() является noexcept,

Может избыточно включать функции C, такие как fclose(FILE*) в блоке try / catch, поскольку они не исключаются, но такие функции, вероятно, не используются с параметром finally напрямую, а через лямбды, которые также легко можно не пометить как noexcept из забывчивости.

4) Статическое утверждение, что f_() нет, кроме

Пользователь должен явно пометить свой код как noexcept каждый раз, то ловить или не ловить исключения — его забота. Опять же ограничивает возможности пользователя по проверке ошибок с исключениями, но с хорошим намерением.

4+) 4) плюс некоторая специализация finally (может быть, даже другого отдельного шаблона класса) с семантикой 2), которая свободна от утверждения, но должна использоваться явно.

4

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]