C++17 has a new attribute, [[nodiscard]]
.
Suppose, that I have a Result
struct, which has this attribute:
struct [[nodiscard]] Result {
};
Now, if I call a function which returns Result
, I got a warning if I don't check the returned Result
:
Result someFunction();
int main() {
someFunction(); // warning here, as I don't check someFunction's return value
}
This program generates:
warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
So far, so good. Now suppose, that I have a special function, for which I still want to return Result
, but I don't want this warning generated, if the check is omitted:
Result someNonCriticalFunction();
int main() {
someNonCriticalFunction(); // I don't want to generate a warning here
}
It is because, someNonCriticalFunction()
does something non-critical (for example, something like printf
- I bet that no-one checks printf
's return value all the time); most cases, I don't care if it fails. But I still want it to return Result
, as in some rare cases, I do need its Result
.
Is it possible to do this somehow?
Possible solutions which I don't like:
(void)someNonCriticalFunction()
, because this function is called a lot of times, it is awkwardsomeNonCriticalFunction()
, which calls (void)someNonCriticalFunction()
: I don't want to have a differently named function just because of this[[nodiscard]]
from Result, and add it to every function which returns Result
It is never necessary to add the [[nodiscard]] attribute. From cppreference: If a function declared nodiscard or a function returning an enumeration or class declared nodiscard by value is called from a discarded-value expression other than a cast to void, the compiler is encouraged to issue a warning.
C++17. The [[nodiscard]] attribute can be used to indicate that the return value of a function shouldn't be ignored when you do a function call. If the return value is ignored, the compiler should give a warning on this.
Why not make use of std::ignore
from the <tuple>
header—that would make the discard explicit:
[[nodiscard]] int MyFunction() { return 42; }
int main()
{
std::ignore = MyFunction();
return 0;
}
std::ignore
: https://en.cppreference.com/w/cpp/utility/tuple/ignore
They say that every problem in computer science can be solved by adding another layer of indirection:
template <bool nodiscard=true>
struct Result;
template <>
struct Result<false> {
// the actual implementation
};
template <>
struct [[nodiscard]] Result<true>
: Result<false>
{
using Result<false>::Result;
};
This is effectively making Result
conditionally [[nodiscard]]
, which allows:
Result<true> someFunction();
Result<false> someNonCriticalFunction();
int main() {
someFunction(); // warning here
someNonCriticalFunction(); // no warning here
}
Although really, this is identical to:
- removing
[[nodiscard]]
from Result, and add it to every function which returns Result
which gets my vote to begin with.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With