为什么 std::move 在 C++20 中不是 [[nodiscard]]?

Why is std::move not [[nodiscard]] in C++20?

本文关键字:nodiscard std move C++20 为什么      更新时间:2023-10-16

我最近在 C++17 中读到了[[nodiscard]],据我所知,这是一个新功能(合同设计?),它迫使你使用返回值。这对于像std::launder这样的有争议的函数是有意义的(自 C++20 年以来的 nodiscard),但我想知道为什么std::move在 C++17/20 中没有这样定义。你知道一个很好的理由还是因为C++20尚未最终确定?

自VS 2017 15.6以来,MSVC标准库团队继续添加数千个[[nodiscard]]实例,并报告了它的巨大成功(无论是在发现大量错误方面还是在未产生用户投诉方面)。他们描述的标准大致是:

  1. 纯观察者,例如vector::size()vector::empty,甚至std::count_if()
  2. 获取原始资源的事物,例如allocate()
  3. 丢弃返回值极有可能导致错误代码的函数,例如std::remove()

MSVC 确实按照这些标准将std::move()std::forward()标记为[[nodiscard]]

虽然它没有在标准中正式注释,但它似乎提供了明显的用户利益,更多的是制作这样一篇论文来标记所有正确的东西[[nodiscard]](再次,来自 MSVC 的数千个实例)并应用它们——它本身并不复杂,但体积很大。与此同时,也许可以刺激您最喜欢的标准库供应商并要求他们[[nodiscard]]很多东西?

AFAIK P0600R1 是将[[nodiscard]]添加到应用于 C++20 的标准库中的唯一建议。从那篇论文:

我们建议采取保守的方法:

[...]

在以下情况下不应添加它:

  • [...]
  • 不使用返回值没有意义,但不会造成伤害,通常不是错误
  • [...]

因此,如果出现这种情况,[[nodiscard]] 不应该发出错误代码的信号

  • [...]
  • 不会
  • 造成伤害,并且可能没有状态更改意味着不会发生

所以原因是标准库使用了一种保守的方法,而还没有提出更激进的方法。