9

C++17 有一个新属性,[[nodiscard]].

假设我有一个Result结构,它具有以下属性:

struct [[nodiscard]] Result {
};

现在,如果我调用一个返回的函数,Result如果我不检查返回的,我会收到一个警告Result

Result someFunction();

int main() {
    someFunction(); // warning here, as I don't check someFunction's return value
}

该程序生成:

警告:忽略使用“nodiscard”属性声明的函数的返回值 [-Wunused-result]

到目前为止,一切都很好。现在假设,我有一个特殊的功能,我仍然想返回Result,但我不希望生成这个警告,如果检查被省略:

Result someNonCriticalFunction();

int main() {
    someNonCriticalFunction(); // I don't want to generate a warning here
}

这是因为,someNonCriticalFunction()做了一些非关键的事情(例如,像printf- 我打赌没有人printf一直检查 ' 的返回值);大多数情况下,我不在乎它是否失败。但我仍然希望它返回Result,因为在极少数情况下,我确实需要它的Result.

有可能以某种方式做到这一点吗?


我不喜欢的可能解决方案:

  • 我不喜欢叫它 as (void)someNonCriticalFunction(),因为这个函数被调用了很多次,很尴尬
  • 创建一个包装器someNonCriticalFunction(),它调用(void)someNonCriticalFunction():我不想仅仅因为这个而有一个不同命名的函数
  • 从 Result 中删除[[nodiscard]],并将其添加到每个返回的函数中Result
4

4 回答 4

22

为什么不std::ignore从头中使用<tuple>——这会使丢弃明确:

[[nodiscard]] int MyFunction() { return 42; }

int main() 
{
    std::ignore = MyFunction();
    return 0;
}
于 2021-10-19T06:45:22.670 回答
7

他们说计算机科学中的每个问题都可以通过添加另一层间接来解决:

template <bool nodiscard=true>
struct Result;

template <>
struct Result<false> {
    // the actual implementation
};

template <>
struct [[nodiscard]] Result<true>
    : Result<false>
{
    using Result<false>::Result;
};

这实际上是Result有条件地制作[[nodiscard]],它允许:

Result<true> someFunction();
Result<false> someNonCriticalFunction();

int main() {
    someFunction();            // warning here
    someNonCriticalFunction(); // no warning here
}

尽管实际上,这与以下内容相同:

  • 从 Result 中删除[[nodiscard]],并将其添加到每个返回 Result 的函数中

这让我开始投票。

于 2017-11-03T21:07:13.820 回答
6

我推荐您排除的选项:

[[nodiscard]]从中删除Result,并将其添加到每个返回 Result 的函数中。”

但是由于您似乎对此不满意,所以这是另一个解决方案,使用沼泽标准继承:

struct [[nodiscard]] Result {
};

struct DiscardableResult: public Result {
};

对于可以丢弃结果的函数,请DiscardableResult用作返回类型:

Result func1();
DiscardableResult func2();

func1(); // will warn
func2(); // will not warn
于 2017-11-03T21:41:02.870 回答
0

将结果转换为 (void *)。

int main()
{
    (void *)someFunction(); //Warning will be gone.
}

这样,就编译器而言,您“使用”了您的结果。非常适合当您使用已使用 nodiscard 的库并且您真的不想知道结果时。

于 2021-07-28T15:54:05.623 回答