Код: Выделить всё
#include
#include
#include
template
class out {
public:
out(T& param, Post check = {})
: param{param},
copy{param}, //must be copyable; may throw
check{std::move(check)}
{}
~out() noexcept(false) {
if (!check(param)) {
param = std::move(copy); //rollback; assume this never throws
if (!std::uncaught_exceptions()) //no exception currently being thrown
throw std::invalid_argument("postcondition violated"); // leaves destructor if another exception is not being thrown
}
}
private:
T& param;
T copy;
Post check;
};
Код: Выделить всё
#include
#include
struct is_not_empty {
bool operator()(const std::vector& v) { return !v.empty(); }
/*not real code, just meant to illustrate the problem*/
is_not_empty() { /*acquire some resource*/ }
~is_not_empty() { /*release some resource*/ }
/******/
};
void function_with_postcondition(out v) {
} // Exception thrown here in out::~out
int main() {
std::vector v; //empty
try {
function_with_postcondition(v);
assert(false); //not reached
}
catch (const std::invalid_argument& e) {
}
}
Я знаю, что такое раскручивание стека, и я знаю, что при этом выбрасывается исключение исключение уже генерируется, что приводит к вызову std::terminate() - этого я пытаюсь избежать с помощью вызова std::uncaught_Exceptions() в деструкторе. Если функция выдает исключение, я не хочу проверять постусловие, поскольку функция завершилась ненормально.
Наконец, почему бы не сделать это другим способом (например, Assert()) , abort(), exit() и т. д.)? Я пытаюсь написать библиотеку, которая проверяет предварительные и постусловия функции и устойчива в аномальных средах. Я пытаюсь уменьшить количество необходимого шаблона, в то же время допуская семантику фиксации/отката, позволяющую повторять операции.
Подробнее здесь: https://stackoverflow.com/questions/790 ... -unwinding