如何有意丢弃[[nodiscard]]返回值?

时间:2018-12-02 15:31:15

标签: c++ c++17

说我有

[[nodiscard]] int foo ()
{
    return 0;
}

int main ()
{
    foo ();
}

然后

error: ignoring return value of ‘int foo()’, declared with attribute nodiscard [-Werror=unused-result]

但如果

int x = foo ();

然后

error: unused variable ‘x’ [-Werror=unused-variable]

是否有一种干净的方法告诉编译器“我想放弃此[[nodiscard]]值”?

5 个答案:

答案 0 :(得分:13)

Cast it to void

[[nodiscard]] int foo ()
{
    return 0;
}

int main ()
{
    static_cast<void>(foo());
}

这基本上告诉编译器“ 是的,我知道我要丢弃它,是的,我确定。

答案 1 :(得分:11)

WG14 nodiscard proposal讨论了允许通过强制转换为无效来使诊断静音的理由。它说强制转换为void是一种鼓励(如果不是非规范性的)方法,可以使其静音,该方法遵循现有实现对__attribute__((warn_unused_result))的作用:

  

[[nodiscard]]属性在现实世界中有广泛的用途,由Clang和GCC实施为__attribute __((warn_unused_result))   ,但由WG21以[[nodiscard]]的名称进行了标准化。该提案选择了标识符nodiscard   因为偏离此名称会导致与C ++不必要的不​​兼容。

     

此属性的语义在很大程度上取决于使用的概念,   定义由实施人员自行决定。然而,   WG21指定的非规范性指南旨在鼓励   nodiscard功能时发出警告诊断的实现   在潜在评估的舍弃值表达式中使用call   除非它是明确强制转换为空的。这意味着   不鼓励实现执行数据流分析(例如   需要初始化但未使用的局部变量诊断)。   ...

C ++的方式为static_cast<void>

请参阅C ++标准草案[[dcl.attr.nodiscard]p2

  

[注:nodiscard调用是一个函数调用表达式,它调用先前声明为nodiscard的函数,或者其返回类型是可能的cv限定类或标记为nodiscard的枚举类型。   不建议将nodiscard调用显示为可能评估的舍弃值表达式,除非明确将其强制转换为void。   在这种情况下,实现应发出警告。   这通常是因为丢弃nodiscard调用的返回值会产生令人惊讶的后果。   —注释]

这是一条注释,因此不是规范性的,但基本上这是现有实现对__attribute__((warn_unused_result))所做的工作。另外,请注意,对 nodiscard 的诊断也是非规范的,因此,对违反 nodiscard 的诊断不是错误的形式,而是实现质量,就像通过强制转换来抑制一样就是这样。

请参见clang document on nodiscard, warn_unused_result

  

Clang支持诊断在可疑情况下何时丢弃函数调用表达式的结果的功能。当函数或其返回类型标记为[[nodiscard]](或__attribute __((warn_unused_result))),并且函数调用显示为可能评估的舍弃表达式(未明确转换)时,将生成诊断。无效。

答案 2 :(得分:8)

您还可以使用另一个标签来标记返回的int

[[nodiscard]] int foo ()
{
    return 0;
}

int main ()
{
    [[maybe_unused]] int i = foo ();
}

如果您有一些需要该值的仅调试代码,则可能很有用。

答案 3 :(得分:4)

我使用(空的)辅助函数“丢弃”

import shapeless.syntax.singleton._

...
KN(1.narrow)

故意丢弃[[nodiscard]]值。

答案 4 :(得分:2)

With Boost

#include <boost/core/ignore_unused.hpp>
int main ()
{
    boost::ignore_unused(foo ());
}

boost::ignore_unused 通过对 const 的引用来获取其参数,因此该参数必须是您可以绑定到对 const 的引用的东西。我相当确定任何可以是函数返回类型的东西(当然,除了 void!)在这里应该没问题。