Skip to content

Commit e8f41bc

Browse files
authored
Merge pull request #434 from CaseyCarter/algminmax
New issue: Use of "smaller" and "larger" in min, max, and minmax is unclear
2 parents 2a0e7c6 + 82aeb65 commit e8f41bc

File tree

1 file changed

+312
-0
lines changed

1 file changed

+312
-0
lines changed

xml/issue4167.xml

Lines changed: 312 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
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&lt;class T&gt;
51+
constexpr const T&amp; min(const T&amp; a, const T&amp; b);
52+
template&lt;class T, class Compare&gt;
53+
constexpr const T&amp; min(const T&amp; a, const T&amp; b, Compare comp);
54+
template&lt;class T, class Proj = identity,
55+
indirect_strict_weak_order&lt;projected&lt;const T*, Proj&gt;&gt; Comp = ranges::less&gt;
56+
constexpr const T&amp; ranges::min(const T&amp; a, const T&amp; 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&lt;class T&gt;
89+
constexpr T min(initializer_list&lt;T&gt; r);
90+
template&lt;class T, class Compare&gt;
91+
constexpr T min(initializer_list&lt;T&gt; r, Compare comp);
92+
template&lt;copyable T, class Proj = identity,
93+
indirect_strict_weak_order&lt;projected&lt;const T*, Proj&gt;&gt; Comp = ranges::less&gt;
94+
constexpr T ranges::min(initializer_list&lt;T&gt; r, Comp comp = {}, Proj proj = {});
95+
template&lt;input_range R, class Proj = identity,
96+
indirect_strict_weak_order&lt;projected&lt;iterator_t&lt;R&gt;, Proj&gt;&gt; Comp = ranges::less&gt;
97+
requires indirectly_copyable_storable&lt;iterator_t&lt;R&gt;, range_value_t&lt;R&gt;*&gt;
98+
constexpr range_value_t&lt;R&gt;
99+
ranges::min(R&amp;&amp; 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) &gt; 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&lt;class T&gt;
133+
constexpr const T&amp; max(const T&amp; a, const T&amp; b);
134+
template&lt;class T, class Compare&gt;
135+
constexpr const T&amp; max(const T&amp; a, const T&amp; b, Compare comp);
136+
template&lt;class T, class Proj = identity,
137+
indirect_strict_weak_order&lt;projected&lt;const T*, Proj&gt;&gt; Comp = ranges::less&gt;
138+
constexpr const T&amp; ranges::max(const T&amp; a, const T&amp; 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&lt;class T&gt;
170+
constexpr T max(initializer_list&lt;T&gt; r);
171+
template&lt;class T, class Compare&gt;
172+
constexpr T max(initializer_list&lt;T&gt; r, Compare comp);
173+
template&lt;copyable T, class Proj = identity,
174+
indirect_strict_weak_order&lt;projected&lt;const T*, Proj&gt;&gt; Comp = ranges::less&gt;
175+
constexpr T ranges::max(initializer_list&lt;T&gt; r, Comp comp = {}, Proj proj = {});
176+
template&lt;input_range R, class Proj = identity,
177+
indirect_strict_weak_order&lt;projected&lt;iterator_t&lt;R&gt;, Proj&gt;&gt; Comp = ranges::less&gt;
178+
requires indirectly_copyable_storable&lt;iterator_t&lt;R&gt;, range_value_t&lt;R&gt;*&gt;
179+
constexpr range_value_t&lt;R&gt;
180+
ranges::max(R&amp;&amp; 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) &gt; 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&lt;class T&gt;
217+
constexpr pair&lt;const T&amp;, const T&amp;&gt; minmax(const T&amp; a, const T&amp; b);
218+
template&lt;class T, class Compare&gt;
219+
constexpr pair&lt;const T&amp;, const T&amp;&gt; minmax(const T&amp; a, const T&amp; b, Compare comp);
220+
template&lt;class T, class Proj = identity,
221+
indirect_strict_weak_order&lt;projected&lt;const T*, Proj&gt;&gt; Comp = ranges::less&gt;
222+
constexpr ranges::minmax_result&lt;const T&amp;&gt;
223+
ranges::minmax(const T&amp; a, const T&amp; 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&lt;class T&gt;
255+
constexpr pair&lt;T, T&gt; minmax(initializer_list&lt;T&gt; t);
256+
template&lt;class T, class Compare&gt;
257+
constexpr pair&lt;T, T&gt; minmax(initializer_list&lt;T&gt; t, Compare comp);
258+
template&lt;copyable T, class Proj = identity,
259+
indirect_strict_weak_order&lt;projected&lt;const T*, Proj&gt;&gt; Comp = ranges::less&gt;
260+
constexpr ranges::minmax_result&lt;T&gt;
261+
ranges::minmax(initializer_list&lt;T&gt; r, Comp comp = {}, Proj proj = {});
262+
template&lt;input_range R, class Proj = identity,
263+
indirect_strict_weak_order&lt;projected&lt;iterator_t&lt;R&gt;, Proj&gt;&gt; Comp = ranges::less&gt;
264+
requires indirectly_copyable_storable&lt;iterator_t&lt;R&gt;, range_value_t&lt;R&gt;*&gt;
265+
constexpr ranges::minmax_result&lt;range_value_t&lt;R&gt;&gt;
266+
ranges::minmax(R&amp;&amp; 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) &gt; 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

Comments
 (0)