【问题标题】:Why there is no std::move_if_noexcept counterpart for std::forward in C++11/14?为什么在 C++11/14 中没有 std::move_if_noexcept 对应的 std::forward?
【发布时间】:2014-10-09 13:29:32
【问题描述】:

我看过 Scott Meyers 在 GoingNative2013 “An Effective C++11/14 Sampler”上的演讲,他解释了std::move_if_noexcept 的用法。

所以我认为应该有一个std::forward_if_noexcept 来保证forward 的异常安全?为什么标准库中没有这样的东西?有没有其他保证的可能?

【问题讨论】:

  • 恢复或保留右值是没有意义的。不过,这并不意味着没有此类助手的用例。
  • forward_if_noexcept 的语义是什么?即,与move_if_noexcept? 相比
  • “也保证forward 的异常安全性” 我不确定我理解你的意思。 move_if_noexcept 没有比move 更多或更少的异常安全保证:它是noexcept,只是一个演员表。 move_if_noexcept 可用于保存对象,即,如果移动失败,则能够恢复以前的状态。
  • Niall,forward 能够处理通用引用,因此使用折叠规则,如果我使用带有 Typededuction 和 T&& 的 Templatefunction,并且我用右值调用它 -> 如果我调用它,它将移动它带有左值->它将复制。因此,在我看来,如果没有 noexcept,forward_if_noexcept 应该向前扩展以复制,否则是旧的行为。
  • @BenjaminSchmidt,有趣的问题和理由。

标签: c++ c++11 perfect-forwarding noexcept


【解决方案1】:

前向语义已经是有条件的,即它们保留其参数的值类别。另一方面,移动无条件地将其参数的值类别(从左值到右值)更改为右值(引用),std::move_if_noexcept 根据是否获得结果值类别移动构造函数不会抛出异常,实际上也使其成为条件。

简而言之,std::forward 不会改变任何东西,它保留了值类别。另一方面,std::move 确实改变了值类别。所以引入std::move_if_noexcept是说如果std::move的改变会导致异常,那么什么都不要改变;不要动它。

我认为这里的基本原理也适用于所有事物 std::move 和 std::forward 的预期惯用用法。在 Scott 关于“通用引用”、转发和移动的其他演讲之一(可能在 C++ 和 Beyond 2012)中,他非常强调转发的惯用用法,我认为这支持了很多 std::forward 是什么以及如何它被使用。它也可能像从未考虑过的那样简单。

我认为没有必要,或者至少当std::forward 生效时需求减少了。

鉴于它可能有一个用例,实施一个不会太难;但我不确定一般用例。可以说,与可能的异常相关的条件以及所需的异常保证应该在执行转发的函数之外进行测试和处理。

template <class U, class T>
U wrapper(T&& arg)
{
    return U(forward<T>(arg));
}

template <class U, class T>
U method() 
{
  T t;
  // work with t
  return wrapper<U>(move_if_noexcept(t));
}

诚然,这其中很多都处于“早期”阶段,因此可能会发生变化。

【讨论】:

  • 如果我是假的,请纠正我,但std::forward 的条件不检查noexcept,所以我认为如果参数是右值,它会调用std::move,所以没有保存?
  • @BenjaminSchmidt,我不知道noexcept 有任何检查,但forward 实际上并没有调用move,它只是一个static_cast(就像move 一样)对参数和类型进行一些错误检查
  • 你是对的,我使用“移动调用”作为一种方法来可视化调用 forward 时会发生什么,实际的实现是不同的,而且肯定更有效
  • @BenjaminSchmidt,我不记得是 Scott 关于转发和移动的那次谈话还是其他谈话,但他非常强调 forward 的惯用用法,我认为这支持了很多什么是 forward 以及如何使用它。
  • 我认为这是在 C++ 和 2012 年以后的版本中,我在 19:52 引用 channel9.msdn.com/Events/GoingNative/2013/… 他用一段示例代码解释了 std::forward 的行为(就像我调用 move :o) )
猜你喜欢
  • 2014-10-15
  • 1970-01-01
  • 1970-01-01
  • 2013-09-14
  • 2014-06-12
  • 1970-01-01
  • 1970-01-01
  • 2014-12-20
  • 2012-10-17
相关资源
最近更新 更多