43

说我有

[[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]]值”?

4

6 回答 6

37

将其转换为void

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

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

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

于 2018-12-02T15:34:09.467 回答
29

WG14 nodiscard 提案讨论了通过将诊断设置为无效来使诊断静音的基本原理。它说强制转换为 void 是鼓励(如果非规范)使其静音的方式,它遵循现有实现的做法__attribute__((warn_unused_result))

[[nodiscard]] 属性具有广泛的实际用途,由 Clang 和 GCC 实现为 __attribute__((warn_unused_result)) ,但由 WG21 以 [[nodiscard]] 的名称进行标准化。这个提议选择了标识符 nodiscard,因为偏离这个名字会造成与 C++ 的不必要的不​​兼容。

该属性的语义很大程度上依赖于使用的概念,其定义由实现自行决定。但是,WG21 指定的非规范性指南是鼓励实现在潜在评估的丢弃值表达式中使用 nodiscard 函数调用时发出警告诊断,除非它是显式转换为 void。这意味着不鼓励实现执行数据流分析(例如需要初始化但未使用的局部变量诊断)。...

C++ 方式是static_cast<void>.

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

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

这是一个注释,因此不规范,但基本上这是现有实现对__attribute__((warn_unused_result)). 此外,请注意nodiscard的诊断也是非规范性的,因此违反nodiscard的诊断不是格式错误的,而是执行质量,就像通过强制转换为 void 进行抑制一样。

请参阅nodiscard 上的 clang 文档 warn_unused_result

Clang 支持诊断在可疑情况下何时丢弃函数调用表达式的结果的能力。当函数或其返回类型被标记为 [[nodiscard]](或 __attribute__((warn_unused_result)))并且函数调用显示为未显式强制转换为 void 的潜在评估丢弃值表达式时,将生成诊断。

于 2018-12-02T15:54:00.797 回答
16

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

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

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

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

于 2018-12-02T15:36:47.320 回答
9

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

template<typename T>
void discard(const T&) {}

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

int main ()
{
    discard(foo());
}

故意丢弃 [[nodiscard]] 值。

于 2020-03-02T08:16:13.180 回答
6

CppCoreGuidelines建议使用std::ignore

永远不要(void)忽略[[nodiscard]]返回值。如果您故意要丢弃这样的结果,请首先认真考虑这是否真的是一个好主意(通常有一个很好的理由,[[nodiscard]]首先使用函数或返回类型的作者)。如果您仍然认为它合适并且您的代码审查者同意,请使用std::ignore =关闭警告,它简单、可移植且易于 grep。

boost::ignore_unused这与另一个答案中的建议几乎相同,但开箱即std::用。

但是,使用 有以下缺点std::ignore

  • 像其他此类辅助函数一样,它将实例化,花费编译时间,并被调用(在非优化调试中),花费运行时间
  • std::ignore用于其他目的
  • std::ignore甚至不能保证抑制警告
于 2021-08-12T16:14:49.227 回答
2

带升压

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

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

于 2021-02-18T19:41:48.653 回答