是否有一个 C++ 标准类可以在作用域退出时将变量设置为值

2024-02-25

在成员函数的范围内,我想临时将成员变量设置为某个值。

然后,当这个函数返回时,我想将此成员变量重置为给定的已知值。

为了避免异常和多次返回,我用一个简单的 RAII 类来完成它。它是在成员函数的范围内定义的。

void MyClass::MyMemberFunction() {
    struct SetBackToFalse {
        SetBackToFalse(bool* p): m_p(p) {}
        ~SetBackToFalse() {*m_p=false;}
    private:
        bool* m_p;
    };

    m_theVariableToChange = true;
    SetBackToFalse resetFalse( &m_theVariableToChange ); // Will reset the variable to false.

    // Function body that may throw.
}

这看起来很明显是司空见惯的,我想知道 C++ 标准库中是否有这样的模板类来做这件事?


还没有(已经有相关提案)。但实现一个通用的很简单;

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看起来像(在线演示在这里 http://coliru.stacked-crooked.com/a/f5f75588e2fcba91);

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()>根据所持有函数的特定异常,为移动构造函数提供异常保证。找到了此实现的示例here http://coliru.stacked-crooked.com/a/64d5b3a0422d6142
  • 这些异常规范与 C++ 提案和 GSL 实现一致
  • 我已经编辑了大部分动机noexcept,更重要的细节可以在C++提案 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0052r1.pdf
  • 析构函数的“通常”RAII 语义,因此“范围退出”功能适用;它不会throw,这也与 C++11 规范中关于析构函数的默认异常规范的规定一致。看参考参数 http://en.cppreference.com/w/cpp/language/destructor, 所以问答 https://stackoverflow.com/q/130117/3747990, GotW#47 http://www.gotw.ca/gotw/047.htm and HIC++ http://www.codingstandard.com/rule/15-2-1-do-not-throw-an-exception-from-a-destructor/

可以找到其他实现;

  • C++ 提案 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4189.pdf上面提到的和其修订版(截至撰写本文时) http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0052r1.pdf
  • Boost.ScopeExit http://www.boost.org/doc/libs/1_60_0/libs/scope_exit/doc/html/index.html
  • 微软 GSL 实施 https://github.com/Microsoft/GSL/blob/master/gsl/gsl_util
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否有一个 C++ 标准类可以在作用域退出时将变量设置为值 的相关文章

随机推荐