是否有C++标准类将变量设置为范围出口处的值

Did*_*set 13 c++ return raii exception-safety

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

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

为了防止异常和多次返回,我已经使用类似简单的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.
}
Run Code Online (Sandbox Code Playgroud)

看起来很平常,我想知道是否有任何这样的模板类在C++标准库中这样做?

Nia*_*all 9

还没有(有提案).但实现通用的很简单;

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; });
Run Code Online (Sandbox Code Playgroud)

为简单起见,我已经编辑了副本并移动构造函数等...

标记它们= 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) };
}
Run Code Online (Sandbox Code Playgroud)

关于执行情况的说明;

  • std::function<void()>可以用来擦除仿函数的类型.std::function<void()>基于所保持函数的特定异常,在移动构造函数上提供异常保证.此处可找到此实现的示例
  • 这些异常规范与C++提案和GSL实现一致
  • 我已经完成了大部分动机,noexceptC++提案中找到了更为实质性的细节
  • 析构函数的"通常"RAII语义,因此"范围退出"功能适用; 它不会throw,这也与析构函数的默认异常规范上的C++ 11规范一致.参见cppreference,SO Q&A,GotW#47HIC++

可以找到其他实现;

  • (Peter Sommerlad关于你所指的文章有一个新版本:[P0052r1](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0052r1.pdf).) (2认同)