|
| 1 | +<?xml version='1.0' encoding='utf-8' standalone='no'?> |
| 2 | +<!DOCTYPE issue SYSTEM "lwg-issue.dtd"> |
| 3 | + |
| 4 | +<issue num="4167" status="New"> |
| 5 | +<title>Use of "smaller" and "larger" in <tt>min</tt>, |
| 6 | +<tt>max</tt>, and <tt>minmax</tt> is unclear</title> |
| 7 | +<section><sref ref="[alg.min.max]"/></section> |
| 8 | +<submitter>Casey Carter</submitter> |
| 9 | +<date>20 Oct 2024</date> |
| 10 | +<priority>99</priority> |
| 11 | + |
| 12 | +<discussion> |
| 13 | +<p> |
| 14 | +<a href="https://github.com/cplusplus/draft/issues/6747">Editorial issue #6747</a> |
| 15 | +finds it inconsistent that |
| 16 | +the wording for the <tt>max</tt>, <tt>min</tt>, and <tt>minmax</tt> algorithms |
| 17 | +uses "larger" and "smaller" |
| 18 | +- terms normally applied to physical quantities - |
| 19 | +to refer to relationships between values |
| 20 | +which we term "greater" and "lesser" |
| 21 | +everywhere else in the Working Paper. |
| 22 | +Using "greater" and "lesser" would make it no less (pun intended) |
| 23 | +of a problem that we describe the ordering imposed by |
| 24 | +an arbitrary binary predicate as if it is a less-than ordering. |
| 25 | +</p><p> |
| 26 | +For example, <sref ref="[alg.min.max]"/> para 2 says that |
| 27 | +<tt>std::ranges::min(13, 42, std::greater{})</tt> |
| 28 | +"<i>Returns</i>: The smaller value. |
| 29 | +Returns the first argument when |
| 30 | +the arguments are equivalent." |
| 31 | +The smaller of 13 and 42 is 13, which is <em>not</em> what this call yields. |
| 32 | +The reader is supposed to somehow know that "The smaller value" actually means |
| 33 | +"the value we'd call the lesser if the arguments were numbers and |
| 34 | +<tt>comp</tt> described a less-then ordering." |
| 35 | +It would be clearer and more concise to simply say |
| 36 | +it returns <tt>b</tt> if |
| 37 | +<tt>invoke(comp, invoke(proj, b), invoke(proj, a))</tt> yields <tt>true</tt> |
| 38 | +and <tt>a</tt> otherwise. |
| 39 | +</p> |
| 40 | +</discussion> |
| 41 | + |
| 42 | +<resolution> |
| 43 | +<p> |
| 44 | +This wording is relative to <paper num="N4993"/>. |
| 45 | +</p> |
| 46 | +<ol> |
| 47 | +<li><p>Modify <sref ref="[alg.min.max]"/> as indicated:</p> |
| 48 | +<blockquote> |
| 49 | +<pre><code> |
| 50 | +template<class T> |
| 51 | + constexpr const T& min(const T& a, const T& b); |
| 52 | +template<class T, class Compare> |
| 53 | + constexpr const T& min(const T& a, const T& b, Compare comp); |
| 54 | +template<class T, class Proj = identity, |
| 55 | + indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> |
| 56 | + constexpr const T& ranges::min(const T& a, const T& b, Comp comp = {}, Proj proj = {}); |
| 57 | +</code></pre> |
| 58 | +</blockquote> |
| 59 | +<p> |
| 60 | +<ins>-?- Let <tt>comp</tt> be <tt>less{}</tt> and |
| 61 | +<tt>proj</tt> be <tt>identity{}</tt> |
| 62 | +for the overloads with no parameters by those names.</ins> |
| 63 | +</p><p> |
| 64 | +-1- <i>Preconditions</i>: |
| 65 | +For the first form, <tt>T</tt> meets the |
| 66 | +<tt><i>Cpp17LessThanComparable</i></tt> requirements |
| 67 | +(Table [tab:cpp17.lessthancomparable]). |
| 68 | +</p><p> |
| 69 | +-2- <del><i>Returns</i>: The smaller value. |
| 70 | +Returns the first argument |
| 71 | +when the arguments are equivalent.</del> |
| 72 | +<ins><i>Effects</i>: Equivalent to:</ins> |
| 73 | +</p> |
| 74 | +<blockquote><pre><ins> |
| 75 | +return invoke(comp, invoke(proj, b), invoke(proj, a)) ? b : a; |
| 76 | +</ins></pre></blockquote> |
| 77 | +<p><del> |
| 78 | +-3- <i>Complexity</i>: Exactly one comparison |
| 79 | +and two applications of the projection, if any. |
| 80 | +</del></p><p> |
| 81 | +-4- <i>Remarks</i>: An invocation may explicitly specify |
| 82 | +an argument for the template parameter <tt>T</tt> |
| 83 | +of the overloads in namespace <tt>std</tt>. |
| 84 | +</p> |
| 85 | + |
| 86 | +<blockquote> |
| 87 | +<pre><code> |
| 88 | +template<class T> |
| 89 | + constexpr T min(initializer_list<T> r); |
| 90 | +template<class T, class Compare> |
| 91 | + constexpr T min(initializer_list<T> r, Compare comp); |
| 92 | +template<copyable T, class Proj = identity, |
| 93 | + indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> |
| 94 | + constexpr T ranges::min(initializer_list<T> r, Comp comp = {}, Proj proj = {}); |
| 95 | +template<input_range R, class Proj = identity, |
| 96 | + indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> |
| 97 | + requires indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*> |
| 98 | + constexpr range_value_t<R> |
| 99 | + ranges::min(R&& r, Comp comp = {}, Proj proj = {}); |
| 100 | +</code></pre> |
| 101 | +</blockquote> |
| 102 | +<p> |
| 103 | +<ins>-?- Let <tt>comp</tt> be <tt>less{}</tt> and <tt>proj</tt> be |
| 104 | +<tt>identity{}</tt> for the overloads with no parameters by those names.</ins> |
| 105 | +</p><p> |
| 106 | +-5- <i>Preconditions</i>: <tt>ranges::distance(r) > 0</tt>. |
| 107 | +For the overloads in namespace <tt>std</tt>, <tt>T</tt> meets the |
| 108 | +<i><tt>Cpp17CopyConstructible</tt></i> requirements |
| 109 | +<ins>(Table [tab:cpp17.copyconstructible])</ins>. |
| 110 | +For the first form, <tt>T</tt> meets the |
| 111 | +<i><tt>Cpp17LessThanComparable</tt></i> requirements |
| 112 | +(Table [tab:cpp17.lessthancomparable]). |
| 113 | +</p><p> |
| 114 | +-6- <i>Returns</i>: <del>The smallest value in the input range. |
| 115 | +Returns a copy of the leftmost element |
| 116 | +when several elements are equivalent to the smallest.</del> |
| 117 | +<ins>Returns a copy of the leftmost element <tt>e</tt> |
| 118 | +in the input range <tt>r</tt> for which |
| 119 | +<tt>bool(invoke(comp, invoke(proj, x), invoke(proj, e)))</tt> |
| 120 | +is <tt>false</tt> for all elements <tt>x</tt> in <tt>r</tt>.</ins> |
| 121 | +</p><p> |
| 122 | +-7- <i>Complexity</i>: Exactly <tt>ranges::distance(r) - 1</tt> comparisons and |
| 123 | +twice as many applications of the projection<del>, if any</del>. |
| 124 | +</p><p> |
| 125 | +-8- <i>Remarks</i>: An invocation may explicitly specify an argument |
| 126 | +for the template parameter <tt>T</tt> |
| 127 | +of the overloads in namespace <tt>std</tt>. |
| 128 | +</p> |
| 129 | + |
| 130 | +<blockquote> |
| 131 | +<pre><code> |
| 132 | +template<class T> |
| 133 | + constexpr const T& max(const T& a, const T& b); |
| 134 | +template<class T, class Compare> |
| 135 | + constexpr const T& max(const T& a, const T& b, Compare comp); |
| 136 | +template<class T, class Proj = identity, |
| 137 | + indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> |
| 138 | + constexpr const T& ranges::max(const T& a, const T& b, Comp comp = {}, Proj proj = {}); |
| 139 | +</code></pre> |
| 140 | +</blockquote> |
| 141 | +<p> |
| 142 | +<ins> |
| 143 | +-?- Let <tt>comp</tt> be <tt>less{}</tt> |
| 144 | +and <tt>proj</tt> be <tt>identity{}</tt> |
| 145 | +for the overloads with no parameters by those names. |
| 146 | +</ins> |
| 147 | +</p><p> |
| 148 | +-9- <i>Preconditions</i>: For the first form, |
| 149 | +<tt>T</tt> meets the <i><tt>Cpp17LessThanComparable</tt></i> requirements |
| 150 | +(Table [tab:cpp17.lessthancomparable]). |
| 151 | +</p><p> |
| 152 | +-10- <del><i>Returns</i>: The larger value. |
| 153 | +Returns the first argument when the arguments are equivalent.</del> |
| 154 | +<ins><i>Effects</i>: Equivalent to:</ins> |
| 155 | +<blockquote><pre><ins> |
| 156 | +return invoke(comp, invoke(proj, a), invoke(proj, b)) ? b : a; |
| 157 | +</ins></pre></blockquote> |
| 158 | +</p><p> |
| 159 | +<del>-11- <i>Complexity</i>: Exactly one comparison |
| 160 | +and two applications of the projection, if any.</del> |
| 161 | +</p><p> |
| 162 | +-12- <i>Remarks</i>: An invocation may explicitly specify an argument |
| 163 | +for the template parameter <tt>T</tt> |
| 164 | +of the overloads in namespace <tt>std</tt>. |
| 165 | +</p> |
| 166 | + |
| 167 | +<blockquote> |
| 168 | +<pre><code> |
| 169 | +template<class T> |
| 170 | + constexpr T max(initializer_list<T> r); |
| 171 | +template<class T, class Compare> |
| 172 | + constexpr T max(initializer_list<T> r, Compare comp); |
| 173 | +template<copyable T, class Proj = identity, |
| 174 | + indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> |
| 175 | + constexpr T ranges::max(initializer_list<T> r, Comp comp = {}, Proj proj = {}); |
| 176 | +template<input_range R, class Proj = identity, |
| 177 | + indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> |
| 178 | + requires indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*> |
| 179 | + constexpr range_value_t<R> |
| 180 | + ranges::max(R&& r, Comp comp = {}, Proj proj = {}); |
| 181 | +</code></pre> |
| 182 | +</blockquote> |
| 183 | +<p> |
| 184 | +<ins> |
| 185 | +-?- Let <tt>comp</tt> be <tt>less{}</tt> |
| 186 | +and <tt>proj</tt> be <tt>identity{}</tt> |
| 187 | +for the overloads with no parameters by those names. |
| 188 | +</ins> |
| 189 | +</p><p> |
| 190 | +-13- <i>Preconditions</i>: <tt>ranges::distance(r) > 0</tt>. |
| 191 | +For the overloads in namespace <tt>std</tt>, |
| 192 | +<tt>T</tt> meets the <i><tt>Cpp17CopyConstructible</tt></i> requirements |
| 193 | +<ins>(Table [tab:cpp17.copyconstructible])</ins>. |
| 194 | +For the first form, <tt>T</tt> meets |
| 195 | +the <i><tt>Cpp17LessThanComparable</tt></i> requirements |
| 196 | +(Table [tab:cpp17.lessthancomparable]). |
| 197 | +</p><p> |
| 198 | +-14- <i>Returns</i>: <del>The largest value in the input range. |
| 199 | +Returns a copy of the leftmost element |
| 200 | +when several elements are equivalent to the largest.</del> |
| 201 | +<ins>Returns a copy of the leftmost element <tt>e</tt> |
| 202 | +in the input range <tt>r</tt> for which |
| 203 | +<tt>bool(invoke(comp, invoke(proj, e), invoke(proj, x)))</tt> |
| 204 | +is <tt>false</tt> for all elements <tt>x</tt> in <tt>r</tt>.</ins> |
| 205 | +</p><p> |
| 206 | +-15- <i>Complexity</i>: Exactly <tt>ranges::distance(r) - 1</tt> comparisons |
| 207 | +and twice as many applications of the projection<del>, if any</del>. |
| 208 | +</p><p> |
| 209 | +-16- <i>Remarks</i>: An invocation may explicitly specify an argument |
| 210 | +for the template parameter <tt>T</tt> |
| 211 | +of the overloads in namespace <tt>std</tt>. |
| 212 | +</p> |
| 213 | + |
| 214 | +<blockquote> |
| 215 | +<pre><code> |
| 216 | +template<class T> |
| 217 | + constexpr pair<const T&, const T&> minmax(const T& a, const T& b); |
| 218 | +template<class T, class Compare> |
| 219 | + constexpr pair<const T&, const T&> minmax(const T& a, const T& b, Compare comp); |
| 220 | +template<class T, class Proj = identity, |
| 221 | + indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> |
| 222 | + constexpr ranges::minmax_result<const T&> |
| 223 | + ranges::minmax(const T& a, const T& b, Comp comp = {}, Proj proj = {}); |
| 224 | +</code></pre> |
| 225 | +</blockquote> |
| 226 | +<p> |
| 227 | +<ins> |
| 228 | +-?- Let <tt>comp</tt> be <tt>less{}</tt> |
| 229 | +and <tt>proj</tt> be <tt>identity{}</tt> |
| 230 | +for the overloads with no parameters by those names. |
| 231 | +</ins> |
| 232 | +</p><p> |
| 233 | +-17- <i>Preconditions</i>: For the first form, |
| 234 | +<tt>T</tt> meets the <i><tt>Cpp17LessThanComparable</tt></i> requirements |
| 235 | +(Table [tab:cpp17.lessthancomparable]). |
| 236 | +</p><p> |
| 237 | +-18- <i>Returns</i>: <tt>{b, a}</tt> |
| 238 | +if <del><tt>b</tt> is smaller than <tt>a</tt></del> |
| 239 | +<ins> |
| 240 | +<tt>bool(invoke(comp, invoke(proj, b), invoke(proj, a)))</tt> is <tt>true</tt> |
| 241 | +</ins>, |
| 242 | +and <tt>{a, b}</tt> otherwise. |
| 243 | +</p><p> |
| 244 | +-19- <i>Complexity</i>: Exactly one comparison |
| 245 | +and two applications of the projection<del>, if any</del>. |
| 246 | +</p><p> |
| 247 | +-20- <i>Remarks</i>: An invocation may explicitly specify an argument |
| 248 | +for the template parameter <tt>T</tt> |
| 249 | +of the overloads in namespace <tt>std</tt>. |
| 250 | +</p> |
| 251 | + |
| 252 | +<blockquote> |
| 253 | +<pre><code> |
| 254 | +template<class T> |
| 255 | + constexpr pair<T, T> minmax(initializer_list<T> t); |
| 256 | +template<class T, class Compare> |
| 257 | + constexpr pair<T, T> minmax(initializer_list<T> t, Compare comp); |
| 258 | +template<copyable T, class Proj = identity, |
| 259 | + indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> |
| 260 | + constexpr ranges::minmax_result<T> |
| 261 | + ranges::minmax(initializer_list<T> r, Comp comp = {}, Proj proj = {}); |
| 262 | +template<input_range R, class Proj = identity, |
| 263 | + indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> |
| 264 | + requires indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*> |
| 265 | + constexpr ranges::minmax_result<range_value_t<R>> |
| 266 | + ranges::minmax(R&& r, Comp comp = {}, Proj proj = {}); |
| 267 | +</code></pre> |
| 268 | +</blockquote> |
| 269 | +<p> |
| 270 | +<ins> |
| 271 | +-?- Let <tt>comp</tt> be <tt>less{}</tt> |
| 272 | +and <tt>proj</tt> be <tt>identity{}</tt> |
| 273 | +for the overloads with no parameters by those names. |
| 274 | +</ins> |
| 275 | +</p><p> |
| 276 | +-21- <i>Preconditions</i>: <tt>ranges::distance(r) > 0</tt>. |
| 277 | +For the overloads in namespace <tt>std</tt>, |
| 278 | +<tt>T</tt> meets the <i><tt>Cpp17CopyConstructible</tt></i> requirements |
| 279 | +<ins>(Table [tab:cpp17.copyconstructible])</ins>. |
| 280 | +For the first form, <tt>T</tt> meets |
| 281 | +the <i><tt>Cpp17LessThanComparable</tt></i> requirements |
| 282 | +(Table [tab:cpp17.lessthancomparable]). |
| 283 | +</p><p> |
| 284 | +-22- <i>Returns</i>: Let <tt>X</tt> be the return type. |
| 285 | +Returns <tt>X{x, y}</tt>, |
| 286 | +where <tt>x</tt> is a copy of the leftmost element |
| 287 | +<del>with the smallest value</del> |
| 288 | +<ins> |
| 289 | +in the input range <tt>r</tt> for which |
| 290 | +<tt>bool(invoke(comp, invoke(proj, e), invoke(proj, x)))</tt> |
| 291 | +is <tt>false</tt> for all elements <tt>e</tt> in <tt>r</tt>, |
| 292 | +</ins> |
| 293 | +and <tt>y</tt> <ins>is</ins> a copy of the rightmost element |
| 294 | +<del>with the largest value in the input range</del> |
| 295 | +<ins> |
| 296 | +in <tt>r</tt> for which |
| 297 | +<tt>bool(invoke(comp, invoke(proj, y), invoke(proj, e)))</tt> |
| 298 | +is <tt>false</tt> for all elements <tt>e</tt> in <tt>r</tt> |
| 299 | +</ins> |
| 300 | +. |
| 301 | +</p><p> |
| 302 | +-23- <i>Complexity</i>: At most (3/2)<tt>ranges::distance(r)</tt> |
| 303 | +<del>applications of the corresponding predicate</del><ins>comparisons</ins> |
| 304 | +and twice as many applications of the projection<del>, if any</del>. |
| 305 | +</p><p> |
| 306 | +-24- <i>Remarks</i>: An invocation may explicitly specify an argument |
| 307 | +for the template parameter <tt>T</tt> |
| 308 | +of the overloads in namespace <tt>std</tt>.</p> |
| 309 | +</li> |
| 310 | +</ol> |
| 311 | +</resolution> |
| 312 | +</issue> |
0 commit comments