Здравствуйте, UniqueRSDN, Вы писали:
URS>Как быть с ситуациями, когда вызывающий деструктор код рассчитывает на то, что из деструктора не полетит исключение?
Я думал над этим — проблема с транзитивностью действительно есть. Если объект A использует B, который вдруг начал использовать C кидающий исключения из деструктора — то теперь и B и A, и все кто их агрегирует/наследуют, кидают исключения из деструкторов. Причём есть много кода, который не насчитан на кидающие деструкторы.
Похожая проблема существует с мутабельностью.
Сейчас, безопасно(?) можно использовать объект с кидающими деструкторами в блоке кода, но не как член или родитель класса. Например можно кидать исключения в action у scope(success).
URS>Тот же Саттер, рассуждая о безопасности исключений приходит в выводу, что полной безопасности не получится достичь,
URS>не имея гарантии отсутствия исключений для некоторых функций. Деструктор входит в число этих функций.
По поводу кидающих деструкторов, недавно вышла такая статья:
Evil, or Just Misunderstood?
URS>Ну или более конкретно, как разрулится такая ситуация:
URS>есть непустой стандартный контейнер объектов. он вышел из скоупа и позвался его деструктор.
URS>он начал звать деструкторы у содержащихся в нем объектов, которые делают важные вещи, правильно распознают
URS>контекст вызова деструктора (по исключению или нет) и если не по исключению, то могут бросить его.
URS>допустим исключение бросил первый же деструктор объекта. деструкторы остальных объектов не позвались.
URS>в результате имеем утечку. или там это как-то хитро разруливается?
Если речь идёт именно о стандартном контейнере, то тут особо ничего не поделаешь.
Если о контейнере вообще — то можно следуя идеологии кидания исключения по возможонсти, поймать первое исключение, остальные проглотить, а потом throw;
При текущем положении дел, кидание исключений из деструкторов опасное занятие, даже если не брать во внимание технические проблемы — большинство кода просто не рассчитано на исключения из деструкторов. Я не агитирую за необдуманное кидание исключений из деструкторов налево и направо (несмотря на название топика

)
Но в то же время, помимо непосредственно деструкции и освобождения ресурсов, на деструкторы навешиваются разного рода отложенные действия, например тот же flush, которые могут фэйлится. Проглатывание всех этих фэйлов по-умолчанию — решение далёкое от идеала.
Например, текущая ситуация по-умолчанию(без явных вызовов flush/close/etc, без логирования фэйла(которое может также сфэйлится)):
1. Первый деструктор — фейл, no action
2. Второй деструктор — фейл, no action
3. Обработка молча завершена
или с киданием исключения по возможности:
1. Первый деструктор — фейл, кидает исключение
2. Второй деструктор во время раскрутки — фэйл, кидать нельзя
3. catch первого исключения выше по call-stack'у, в месте ответственном за их обработку
4. информирование пользователя
5. пользователь устраняет причины, и запускает обработку заново
6. Первый деструктор — success
7. Второй деструктор — фэйл (а может и не фэйл, если зависело от первого), кидает исключение
... пользователь узнаёт об этом, исправляет и запускает заново.
Ведь вполне возможный сценарий.
Что лучше?