Created on 2025-05-29.00:00:00 last changed 3 weeks ago
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.
History | |||
---|---|---|---|
Date | User | Action | Args |
2025-05-29 00:00:00 | admin | create |