What are usecases in which it is beneficial to use a [[nodiscard]]
type?
On types, [[nodiscard]]
emits a warning if the return value of any function returning an instance of that type is omitted; (Citation from p0068r0):
If [[nodiscard]] is marked on a type, it makes it so that all functions that return that type are implicitly [[nodiscard]].
while a [[nodiscard]]
constructor (c++2a) is very useful for classes which manage resources (e.g. unique_ptr
) and nodiscard for functions are for instance useful for make_unique
I cannot come up with an example where a nodiscard for a type is useful and I'm interested in cases where it is used.
Consider the type std::unique_lock<M>
. It's an obvious candidate for marking the constructor (specifically the one that takes M&
) nodiscard, as we would not want to write some code like this by accident:
std::unique_lock<M>(m);
// oops! we actually meant
// std::unique_lock<M> lck(m);
This falls under the "manages resources" category.
But this is also an example of a type that we would not want to have discarded if returned from a function:
std::unique_lock<M> getLockFor(Arg x) {
std::unique_lock<M> result;
// acquire some lock based on x
return result;
}
{
auto lck = getLockFor(arg1); // ok
// do some stuff that requires the lock to be held
}
{
getLockFor(arg2); // warning!
// lock will NOT be held here!
}
To get the warning in this case, we would need to mark the type as nodiscard, not just the constructor.
I think, in fact, this example illustrates that perhaps most classes that manage resources should be nodiscard, as it is probably a bug when we call a function that returns to us control over a resource, merely to release that resource immediately by not using the return value.