如何正确推导出一个函数的noexcept-ness?

Jun*_*eon 6 c++ noexcept copy-elision c++17

在通用上下文中,我们经常写类似的东西

return_type f(arg_type1 arg1, ...)
  noexcept(noexcept(statement_1) && noexcept(statement_2) && ... && noexcept(statement_n))
{
  statement_1;
  statement_2;
  ...
  statement_n;
}
Run Code Online (Sandbox Code Playgroud)

当a statement_k是return语句时,事情并非如此简单.这是不可能写的noexcept(return expr).相反,我应该理解当我们说return expr并分解成几个时发生的事情noexcept(something).但它似乎非常重要.

我想出了类似下面的算法:

  1. 如果return_type是参考类型,那么当然noexcept(expr)就足够了.
  2. 如果return_type不是参考类型,但如果return expr是保证复制省略发生的情况,那么再次noexcept(expr)就足够了.
  3. 否则,noexcept(expr) && std::is_nothrow_move_constructible<return_type>::value && std::is_nothrow_destructible<return_type>::value.

这样对吗?或者有更简单的方法吗?案例1将被归入案例3的特例,但案例2和案例3如何?