This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
function<void()>
suppresses nodiscard
warningsSection: 22.10.4 [func.require] Status: New Submitter: Jonathan Wakely Opened: 2025-05-29 Last modified: 2025-05-29
Priority: Not Prioritized
View other active issues in [func.require].
View all other issues in [func.require].
View all issues with New status.
Discussion:
struct [[nodiscard]] A { };
A f();
std::function<void()> func = f;
Invoking func()
will discard the return value of f()
, but there will be
no warning. This is because INVOKE<void>(...)
is defined in terms of static_cast<void>(...)
and the
explicit cast to void suppresses nodiscard
warnings.
This is in contast to INVOKE<R>(...)
where the
conversion to non-void R
is implicit.
It seems right that std::invoke_r<void>(f)
should not give
nodiscard
warnings, because that's quite explicit about converting to void,
and similarly for std::bind<void>(f)()
.
However, I think it's debatable whether all uses of INVOKE<void>
(and std::function<void()>
in particular)
intend an explicit cast to void that ignores nodiscard
types.
It's very easy to set f
as the target of func
and then lose its warning,
and there's no explicit use of void
when you write func = f; func();
.
We could consider defining INVOKE<void>(...)
to be
an expression of type void, without explicitly saying there's a cast to void.
For example, (INVOKE(...), void())
would invoke the invocable and have type
void
, but would not require any nodiscard
warnings to be suppressed.
If we did that, some uses of INVOKE<R>
such as
std::invoke_r
and std::bind<R>
might need to
be adjusted to preserve the explicit conversion to void.
That would allow us to be selective about which uses of
INVOKE<void>
we consider to be explicit about
discarding results, and which we don't.
Proposed resolution: