在特殊情况下是否可以忽略 [[nodiscard]]?
Is it possible to ignore [[nodiscard]] in a special case?
C++17 有一个新属性,[[nodiscard]]
。
假设我有一个 Result
结构,它有这个属性:
struct [[nodiscard]] Result {
};
现在,如果我调用 returns Result
的函数,如果我不检查 returned Result
,我会收到警告:
Result someFunction();
int main() {
someFunction(); // warning here, as I don't check someFunction's return value
}
此程序生成:
warning: ignoring return value of function declared with 'nodiscard'
attribute [-Wunused-result]
到目前为止,还不错。现在假设,我有一个特殊的功能,我仍然想要 return Result
,但我不希望生成此警告,如果省略检查:
Result someNonCriticalFunction();
int main() {
someNonCriticalFunction(); // I don't want to generate a warning here
}
这是因为,someNonCriticalFunction()
做了一些不重要的事情(例如,像 printf
- 我打赌没有人检查 printf
的 return始终保持价值);大多数情况下,我不在乎它是否失败。但我仍然希望它 return Result
,因为在极少数情况下,我确实需要它 Result
.
有没有办法做到这一点?
我不喜欢的可能解决方案:
- 我不想把它叫做
(void)someNonCriticalFunction()
,因为这个函数被调用了很多次,很别扭
- 围绕
someNonCriticalFunction()
创建一个包装器,它调用 (void)someNonCriticalFunction()
:我不想仅仅因为这个就使用不同名称的函数
- 从结果中删除
[[nodiscard]]
,并将其添加到 returns Result
的每个函数
他们说计算机科学中的每个问题都可以通过添加另一个间接层来解决:
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
}
虽然实际上,这与:
- removing
[[nodiscard]]
from Result, and add it to every function which returns Result
首先让我投票。
我推荐你排除的选项:
"removing [[nodiscard]]
from Result
, and add it to every function which returns Result."
但由于您似乎对此不满意,这里有另一个解决方案,使用标准继承:
struct [[nodiscard]] Result {
};
struct DiscardableResult: public Result {
};
对于可以丢弃结果的函数,使用 DiscardableResult
作为 return 类型:
Result func1();
DiscardableResult func2();
func1(); // will warn
func2(); // will not warn
将结果转换为 (void *)。
int main()
{
(void *)someFunction(); //Warning will be gone.
}
就编译器而言,这样您就“使用”了您的结果。非常适合当您使用的库已经使用了 nodiscard 并且您真的不想知道结果时。
为什么不使用 <tuple>
header 中的 std::ignore
——这会使丢弃变得明确:
[[nodiscard]] int MyFunction() { return 42; }
int main()
{
std::ignore = MyFunction();
return 0;
}
- 此代码段的编译器资源管理器:https://godbolt.org/z/eGPsjajz8
std::ignore
的 CPP 参考:https://en.cppreference.com/w/cpp/utility/tuple/ignore
C++17 有一个新属性,[[nodiscard]]
。
假设我有一个 Result
结构,它有这个属性:
struct [[nodiscard]] Result {
};
现在,如果我调用 returns Result
的函数,如果我不检查 returned Result
,我会收到警告:
Result someFunction();
int main() {
someFunction(); // warning here, as I don't check someFunction's return value
}
此程序生成:
warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
到目前为止,还不错。现在假设,我有一个特殊的功能,我仍然想要 return Result
,但我不希望生成此警告,如果省略检查:
Result someNonCriticalFunction();
int main() {
someNonCriticalFunction(); // I don't want to generate a warning here
}
这是因为,someNonCriticalFunction()
做了一些不重要的事情(例如,像 printf
- 我打赌没有人检查 printf
的 return始终保持价值);大多数情况下,我不在乎它是否失败。但我仍然希望它 return Result
,因为在极少数情况下,我确实需要它 Result
.
有没有办法做到这一点?
我不喜欢的可能解决方案:
- 我不想把它叫做
(void)someNonCriticalFunction()
,因为这个函数被调用了很多次,很别扭 - 围绕
someNonCriticalFunction()
创建一个包装器,它调用(void)someNonCriticalFunction()
:我不想仅仅因为这个就使用不同名称的函数 - 从结果中删除
[[nodiscard]]
,并将其添加到 returnsResult
的每个函数
他们说计算机科学中的每个问题都可以通过添加另一个间接层来解决:
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
}
虽然实际上,这与:
- removing
[[nodiscard]]
from Result, and add it to every function which returns Result
首先让我投票。
我推荐你排除的选项:
"removing [[nodiscard]]
from Result
, and add it to every function which returns Result."
但由于您似乎对此不满意,这里有另一个解决方案,使用标准继承:
struct [[nodiscard]] Result {
};
struct DiscardableResult: public Result {
};
对于可以丢弃结果的函数,使用 DiscardableResult
作为 return 类型:
Result func1();
DiscardableResult func2();
func1(); // will warn
func2(); // will not warn
将结果转换为 (void *)。
int main()
{
(void *)someFunction(); //Warning will be gone.
}
就编译器而言,这样您就“使用”了您的结果。非常适合当您使用的库已经使用了 nodiscard 并且您真的不想知道结果时。
为什么不使用 <tuple>
header 中的 std::ignore
——这会使丢弃变得明确:
[[nodiscard]] int MyFunction() { return 42; }
int main()
{
std::ignore = MyFunction();
return 0;
}
- 此代码段的编译器资源管理器:https://godbolt.org/z/eGPsjajz8
std::ignore
的 CPP 参考:https://en.cppreference.com/w/cpp/utility/tuple/ignore