|
| 1 | +<?xml version='1.0' encoding='utf-8' standalone='no'?> |
| 2 | +<!DOCTYPE issue SYSTEM "lwg-issue.dtd"> |
| 3 | + |
| 4 | +<issue num="4175" status="New"> |
| 5 | +<title>`get_env()` specified in terms of `as_const()` but this doesn't work with rvalue senders</title> |
| 6 | +<section><sref ref="[exec.get.allocator]"/><sref ref="[exec.get.stop.token]"/><sref ref="[exec.get.env]"/> |
| 7 | + <sref ref="[exec.get.domain]"/><sref ref="[exec.get.scheduler]"/> |
| 8 | + <sref ref="[exec.get.delegation.scheduler]"/><sref ref="[exec.get.fwd.progress]"/> |
| 9 | + <sref ref="[exec.get.compl.sched]"/></section> |
| 10 | +<submitter>Lewis Baker</submitter> |
| 11 | +<date>10 Nov 2024</date> |
| 12 | +<priority>99</priority> |
| 13 | + |
| 14 | +<discussion> |
| 15 | +<p> |
| 16 | +The current specification of `std::execution::get_env()` defines `get_env(o)` as `as_const(o).get_env()`. |
| 17 | +However, the `as_const()` function has a deleted rvalue-taking overload, meaning that you cannot pass temporaries to it. |
| 18 | +<p/> |
| 19 | +This means that several uses of `get_env()` which pass expressions which are either potentially rvalues |
| 20 | +(e.g. in definition of `connect(sndr, rcvr)` it uses the expression `get_env(rcvr)`, but `rcvr` could be, |
| 21 | +and usually is, a prvalue) or always rvalues (e.g. `scheduler` concept has the expression |
| 22 | +<tt>get_env(schedule(std::forward<Sch>(sch)))</tt>). |
| 23 | +<p/> |
| 24 | +The intent here was that `get_env()` is a function that takes as an argument a <tt>const T&</tt> and thus |
| 25 | +allows prvalues to bind to it. We basically just want to require that `get_env()` finds a const-qualified |
| 26 | +member-function. The use of `as_const()` does not seem to mirror the semantics of a function with a |
| 27 | +<tt>const T&</tt> parameter, so I suggest we change it to something else that expresses the intent. |
| 28 | +</p> |
| 29 | +</discussion> |
| 30 | + |
| 31 | +<resolution> |
| 32 | +<p> |
| 33 | +This wording is relative to <paper num="N4993"/>. |
| 34 | +</p> |
| 35 | + |
| 36 | +<ol> |
| 37 | +<li><p>Add to the end of <sref ref="[exec.general]"/> as indicated:</p> |
| 38 | + |
| 39 | +<blockquote> |
| 40 | +<p> |
| 41 | +<ins>-?- For a subexpression `expr`, let <tt><i>AS-CONST</i>(expr)</tt> be expression-equivalent to</ins> |
| 42 | +</p> |
| 43 | +<blockquote><pre> |
| 44 | +<ins>[](const auto& x) noexcept -> const auto& { return x; }(expr)</ins> |
| 45 | +</pre></blockquote> |
| 46 | +</blockquote> |
| 47 | + |
| 48 | +</li> |
| 49 | + |
| 50 | +<li><p>Modify <sref ref="[exec.get.allocator]"/> as indicated:</p> |
| 51 | + |
| 52 | +<blockquote> |
| 53 | +<p> |
| 54 | +-1- `get_allocator` asks a queryable object for its associated allocator. |
| 55 | +<p/> |
| 56 | +-2- The name `get_allocator` denotes a query object. For a subexpression `env`, `get_allocator(env)` is |
| 57 | +expression-equivalent to <tt><i>MANDATE-NOTHROW</i>(<del>as_const</del><ins><i>AS-CONST</i></ins>(env).query(get_allocator))</tt>. |
| 58 | +</p> |
| 59 | +</blockquote> |
| 60 | + |
| 61 | +</li> |
| 62 | + |
| 63 | +<li><p>Modify <sref ref="[exec.get.stop.token]"/> as indicated:</p> |
| 64 | + |
| 65 | +<blockquote> |
| 66 | +<p> |
| 67 | +-2- The name `get_stop_token` denotes a query object. For a subexpression `env`, `get_stop_token(env)` is |
| 68 | +expression-equivalent to: |
| 69 | +</p> |
| 70 | +<ol style="list-style-type: none"> |
| 71 | +<li><p>(2.1) — <tt><i>MANDATE-NOTHROW</i>(<del>as_const</del><ins><i>AS-CONST</i></ins>(env).query(get_stop_token))</tt> |
| 72 | +if that expression is well-formed.</p></li> |
| 73 | +</ol> |
| 74 | +</blockquote> |
| 75 | + |
| 76 | +</li> |
| 77 | + |
| 78 | +<li><p>Modify <sref ref="[exec.get.env]"/> as indicated:</p> |
| 79 | + |
| 80 | +<blockquote> |
| 81 | +<p> |
| 82 | +-1- `execution::get_env` is a customization point object. For a subexpression `o`, `execution::get_env(o)` is |
| 83 | +expression-equivalent to: |
| 84 | +</p> |
| 85 | +<ol style="list-style-type: none"> |
| 86 | +<li><p>(1.1) — <tt><i>MANDATE-NOTHROW</i>(<del>as_const</del><ins><i>AS-CONST</i></ins>(o).get_env())</tt> |
| 87 | +if that expression is well-formed.</p></li> |
| 88 | +</ol> |
| 89 | +</blockquote> |
| 90 | + |
| 91 | +</li> |
| 92 | + |
| 93 | +<li><p>Modify <sref ref="[exec.get.domain]"/> as indicated:</p> |
| 94 | + |
| 95 | +<blockquote> |
| 96 | +<p> |
| 97 | +-2- The name `get_domain` denotes a query object. For a subexpression `env`, `get_domain(env)` is expression-equivalent |
| 98 | +to <tt><i>MANDATE-NOTHROW</i>(<del>as_const</del><ins><i>AS-CONST</i></ins>(env).query(get_domain))</tt>. |
| 99 | +</p> |
| 100 | + |
| 101 | +</blockquote> |
| 102 | + |
| 103 | +</li> |
| 104 | + |
| 105 | +<li><p>Modify <sref ref="[exec.get.scheduler]"/> as indicated:</p> |
| 106 | + |
| 107 | +<blockquote> |
| 108 | +<p> |
| 109 | +-2- The name `get_scheduler` denotes a query object. For a subexpression `env`, `get_scheduler(env)` is |
| 110 | +expression-equivalent to <tt><i>MANDATE-NOTHROW</i>(<del>as_const</del><ins><i>AS-CONST</i></ins>(env).query(get_scheduler))</tt>. |
| 111 | +</p> |
| 112 | +</blockquote> |
| 113 | + |
| 114 | +</li> |
| 115 | + |
| 116 | +<li><p>Modify <sref ref="[exec.get.delegation.scheduler]"/> as indicated:</p> |
| 117 | + |
| 118 | +<blockquote> |
| 119 | +<p> |
| 120 | +-2- The name `get_delegation_scheduler` denotes a query object. For a subexpression `env`, |
| 121 | +`get_delegation_scheduler(env)` is expression-equivalent to |
| 122 | +<tt><i>MANDATE-NOTHROW</i>(<del>as_const</del><ins><i>AS-CONST</i></ins>(env).query(get_delegation_scheduler))</tt>. |
| 123 | +</p> |
| 124 | +</blockquote> |
| 125 | + |
| 126 | +</li> |
| 127 | + |
| 128 | +<li><p>Modify <sref ref="[exec.get.fwd.progress]"/> as indicated:</p> |
| 129 | + |
| 130 | +<blockquote> |
| 131 | +<p> |
| 132 | +-2- The name `get_forward_progress_guarantee` denotes a query object. For a subexpression `sch`, let |
| 133 | +`Sch` be `decltype((sch))`. If `Sch` does not satisfy `scheduler`, `get_forward_progress_guarantee` is ill-formed. |
| 134 | +Otherwise, `get_forward_progress_guarantee(sch)` is expression-equivalent to: |
| 135 | +</p> |
| 136 | +<ol style="list-style-type: none"> |
| 137 | +<li><p>(2.1) — <tt><i>MANDATE-NOTHROW</i>(<del>as_const</del><ins><i>AS-CONST</i></ins>(sch).query(get_forward_progress_guarantee))</tt> |
| 138 | +if that expression is well-formed.</p></li> |
| 139 | +</ol> |
| 140 | +</blockquote> |
| 141 | + |
| 142 | +</li> |
| 143 | + |
| 144 | +<li><p>Modify <sref ref="[exec.get.compl.sched]"/> as indicated:</p> |
| 145 | + |
| 146 | +<blockquote> |
| 147 | +<p> |
| 148 | +-2- The name `get_completion_scheduler` denotes a query object template. For a subexpression `q`, the expression |
| 149 | +<tt>get_completion_scheduler<<i>completion-tag</i>>(q)</tt> is ill-formed if <tt><i>completion-tag</i></tt> |
| 150 | +is not one of `set_value_t`, `set_error_t`, or `set_stopped_t`. Otherwise, |
| 151 | +<tt>get_completion_scheduler<<i>completion-tag</i>>(q)</tt> is expression-equivalent to |
| 152 | +</p> |
| 153 | +<blockquote><pre> |
| 154 | +<i>MANDATE-NOTHROW</i>(<del>as_const</del><ins><i>AS-CONST</i></ins>(q).query(get_completion_scheduler<<i>completion-tag</i>> |
| 155 | +</pre></blockquote> |
| 156 | +</blockquote> |
| 157 | + |
| 158 | +</li> |
| 159 | + |
| 160 | +</ol> |
| 161 | +</resolution> |
| 162 | + |
| 163 | +</issue> |
0 commit comments