Я только что заметил на
http://en.cppreference.com/w/cpp/error/uncaught_exception
что C ++ 17 заменит std::uncaught_exception()
, который возвращает bool
, с std::uncaught_exceptions()
, который возвращает int
,
Дополнение к стандарту, описывающему это здесь:
http://isocpp.org/files/papers/n4259.pdf
Это не дает обоснования, но говорит
[Примечание: когда uncaught_exceptions ()> 0, исключение может
привести к вызову std :: terminate () (15.5.1). — конец примечания]
что странно расплывчато
В чем причина этого изменения? Будут ли возможны многочисленные активные исключения в C ++ 17 или какой-либо будущей версии стандарта?
Бумага, которая представила это, была n4152, который имеет смысл (который обычно сводится к тому, чтобы «заставить ScopeGuard работать»)
Цитировать,
как задокументировано, по крайней мере, с 1998 года в «Гуру недели № 47», это означает, что код, который транзитивно вызывается из деструктора, который сам может быть вызван при разматывании стека, не может правильно определить, действительно ли он сам вызывается как часть разматывания. Как только вы раскручиваете любое исключение,
uncaught_exception
все выглядит как раскручивание, даже если существует более одного активного исключения.
А также
здесь используется информация, уже представленная в основных реализациях, где текущие реализации ScopeGuard прибегают к непортативному коду, который использует недокументированные функции компилятора, чтобы сделать ScopeGuard «портативным на практике» сегодня. Эта опция предлагает добавить одну новую функцию для отображения информации, которая уже присутствует в компиляторах, так что эти применения могут быть действительно переносимыми
PS: вот пример того, как эта функция может быть реализована с использованием информации, специфичной для компилятора: https://github.com/panaseleus/stack_unwinding/blob/master/boost/exception/uncaught_exception_count.hpp
И для простого примера, где он используется, смотрите не дальше, чем «рекордный насос» boost.log (см. повышение / журнал / подробно / format.hpp а также повышение / Журнал / источники / record_ostream.hpp): это позволяет BOOST_LOG(lg) << foo();
войти в деструктор объекта охраны он создает, если foo
не выдает, то есть, если число исключений в полете при вызове деструктора не больше, чем при вызове конструктора.
std :: uncaught_exception () только определяет, разматывается ли стек. В статье Херба Саттера он указывает, что это не означает, что существует активное исключение. Херб полагает, что это «почти» полезно. Я столкнулся с ситуацией, когда это действительно неоднозначно, что и привело меня к этому посту.
std :: uncaught_exceptions () указывается как возвращающее количество активных исключений, что на самом деле полезно.
обратите внимание, что std :: uncaught_exception () все еще может быть полезен для debug / loginfo. Это может помочь определить, откуда возникло исключение. Однако я согласен функционально, это совершенно бесполезно.