|
| 1 | +<?xml version='1.0' encoding='utf-8' standalone='no'?> |
| 2 | +<!DOCTYPE issue SYSTEM "lwg-issue.dtd"> |
| 3 | + |
| 4 | +<issue num="4268" status="New"> |
| 5 | +<title><code>function<void()></code> suppresses `nodiscard` warnings</title> |
| 6 | +<section><sref ref="[func.require]"/></section> |
| 7 | +<submitter>Jonathan Wakely</submitter> |
| 8 | +<date>29 May 2025</date> |
| 9 | +<priority>99</priority> |
| 10 | + |
| 11 | +<discussion> |
| 12 | +<pre><code>struct [[nodiscard]] A { }; |
| 13 | +A f(); |
| 14 | +std::function<void()> func = f; |
| 15 | +</code></pre> |
| 16 | +<p> |
| 17 | +Invoking `func()` will discard the return value of `f()`, but there will be |
| 18 | +no warning. This is because <code><i>INVOKE</i><void>(...)</code> |
| 19 | +is defined in terms of <code>static_cast<void>(...)</code> and the |
| 20 | +explicit cast to void suppresses `nodiscard` warnings. |
| 21 | +This is in contast to <code><i>INVOKE</i><R>(...)</code> where the |
| 22 | +conversion to non-void `R` is implicit. |
| 23 | +</p> |
| 24 | + |
| 25 | +<p> |
| 26 | +It seems right that <code>std::invoke_r<void>(f)</code> should not give |
| 27 | +`nodiscard` warnings, because that's quite explicit about converting to void, |
| 28 | +and similarly for <code>std::bind<void>(f)()</code>. |
| 29 | +However, I think it's debatable whether all uses of <code><i>INVOKE</i><void></code> (and <code>std::function<void()></code> in particular) |
| 30 | +intend an explicit cast to void that ignores `nodiscard` types. |
| 31 | +It's very easy to set `f` as the target of `func` and then lose its warning, |
| 32 | +and there's no explicit use of `void` when you write `func = f; func();`. |
| 33 | +</p> |
| 34 | +<p> |
| 35 | +We could consider defining <code><i>INVOKE</i><void>(...)</code> to be |
| 36 | +an expression of type void, without explicitly saying there's a cast to void. |
| 37 | +For example, `(INVOKE(...), void())` would invoke the invocable and have type |
| 38 | +`void`, but would not require any `nodiscard` warnings to be suppressed. |
| 39 | +If we did that, some uses of <code><i>INVOKE</i><R></code> such as |
| 40 | +<code>std::invoke_r</code> and <code>std::bind<R></code> might need to |
| 41 | +be adjusted to preserve the explicit conversion to void. |
| 42 | +That would allow us to be selective about which uses of |
| 43 | +<code><i>INVOKE</i><void></code> we consider to be explicit about |
| 44 | +discarding results, and which we don't. |
| 45 | +</p> |
| 46 | +</discussion> |
| 47 | + |
| 48 | +<resolution> |
| 49 | +<p> |
| 50 | +</p> |
| 51 | +</resolution> |
| 52 | + |
| 53 | +</issue> |
0 commit comments