Ответ 1
Пока нет (для этого были предложения). Но реализация родового достаточно проста:
struct scope_exit {
std::function<void()> f_;
explicit scope_exit(std::function<void()> f) noexcept : f_(std::move(f)) {}
~scope_exit() { if (f_) f_(); }
};
// ...
m_theVariableToChange = true;
scope_exit resetFalse([&m_theVariableToChange]() { m_theVariableToChange = false; });
Для простоты выше, я отредактировал копию и переместил конструкторы и т.д.
Маркировка их как = delete
сделает приведенное выше минимальным решением. В дальнейшем; при желании можно разрешить перемещение, но копирование должно быть запрещено.
Более полная scope_exit
будет выглядеть (онлайн-демонстрация здесь);
template <typename F>
struct scope_exit {
F f_;
bool run_;
explicit scope_exit(F f) noexcept : f_(std::move(f)), run_(true) {}
scope_exit(scope_exit&& rhs) noexcept : f_((rhs.run_ = false, std::move(rhs.f_))), run_(true) {}
~scope_exit()
{
if (run_)
f_(); // RAII semantics apply, expected not to throw
}
// "in place" construction expected, no default ctor provided either
// also unclear what should be done with the old functor, should it
// be called since it is no longer needed, or not since *this is not
// going out of scope just yet...
scope_exit& operator=(scope_exit&& rhs) = delete;
// to be explicit...
scope_exit(scope_exit const&) = delete;
scope_exit& operator=(scope_exit const&) = delete;
};
template <typename F>
scope_exit<F> make_scope_exit(F&& f) noexcept
{
return scope_exit<F>{ std::forward<F>(f) };
}
Примечания по реализации;
-
std::function<void()>
может использоваться для стирания типа функтора.std::function<void()>
предлагает гарантии исключения для конструкторов перемещения на основе специфики исключения для удерживаемой функции. Образец этой реализации найден здесь - Эти спецификации исключений согласованы с предложением С++ и реализацией GSL.
- Я отредактировал большую часть мотивации для
noexcept
, более существенные детали найдены в предложение С++ - "Обычная" RAII-семантика деструктора, следовательно, применима функция "выхода области"; он не будет
throw
, это также соответствует спецификации С++ 11 спецификации исключения по умолчанию для деструктора. См. cppreference, SO Q & A, GotW # 47 и HIС++
Можно найти другие реализации:
- Рекомендация С++, упомянутая выше, и ее пересмотр (начиная с это письмо)
- Boost.ScopeExit
- Реализация Microsoft GSL