Skip to content

Commit 85d20a9

Browse files
committed
New issue from Jonathan: unique_copy passes arguments to its predicate backwards
1 parent d5e7322 commit 85d20a9

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

xml/issue4269.xml

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?xml version='1.0' encoding='utf-8' standalone='no'?>
2+
<!DOCTYPE issue SYSTEM "lwg-issue.dtd">
3+
4+
<issue num="4269" status="New">
5+
<title>`unique_copy` passes arguments to its predicate backwards</title>
6+
<section><sref ref="[alg.unique]"/></section>
7+
<submitter>Jonathan Wakely</submitter>
8+
<date>29 May 2025</date>
9+
<priority>99</priority>
10+
11+
<discussion>
12+
<p>
13+
For the `unique` algorithms, <sref ref="[alg.unique]"/> p1 says:
14+
</p>
15+
<blockquote>
16+
1. Let `pred` be `equal_to{}` for the overloads with no parameter `pred`,
17+
and let <i>E</i> be
18+
<ol style="list-style-type: none">
19+
<li> (1.1)
20+
&mdash; `bool(pred(*(i - 1), *i))` for the overloads in namespace `std`;
21+
</li>
22+
<li>(1.2)
23+
&mdash; `bool(invoke(comp, invoke(proj, *(i - 1)), invoke(proj, *i)))`
24+
for the overloads in namespace `ranges`.
25+
</li>
26+
</ol>
27+
</blockquote>
28+
<p>
29+
However for the `unique_copy` algorithms, <sref ref="[alg.unique]"/> p6 says
30+
that the arguments `*i` and `*(i-1)` should be reversed:
31+
</p>
32+
<blockquote>
33+
6. Let `pred` be `equal_to{}` for the overloads with no parameter `pred`,
34+
and let <i>E</i> be
35+
<ol style="list-style-type: none">
36+
<li> (6.1)
37+
&mdash; `bool(pred(*i, *(i - 1)))` for the overloads in namespace `std`;
38+
</li>
39+
<li>(6.2)
40+
&mdash; `bool(invoke(comp, invoke(proj, *i), invoke(proj, *(i - 1))))`
41+
for the overloads in namespace `ranges`.
42+
</li>
43+
</ol>
44+
</blockquote>
45+
<p>
46+
This reversed order is consistent with the documentation for
47+
<a href="https://stl.boost.org/unique_copy.html">SGI STL `unique_copy`</a>,
48+
although the docs for
49+
<a href="https://stl.boost.org/unique_copy.html">SGI STL `unique`</a>
50+
show reversed arguments too, and the C++ standard doesn't match that.
51+
</p>
52+
<p>
53+
A survey of known implementations shows that all three of libstdc++, libc++,
54+
and MSVC STL use the `pred(*(i - 1), *i)` order for all of `std::unique`,
55+
`std::unique_copy`, `ranges::unique`, and `ranges::unique_copy`. The range-v3
56+
library did the same, and even the SGI STL did too (despite what its docs said).
57+
Only two implementations were found which match the spec and use a different
58+
argument order for `unique` and `unique_copy`, Casey Carter's (cmcstl2) and
59+
Fraser Gordon's.
60+
</p>
61+
<p>
62+
In the absence of any known rationale for `unique` and `unique_copy` to differ,
63+
it seems sensible to make `unique_copy` more consistent with `unique`
64+
(and with the majority of implementations stretching back three decades).
65+
</p>
66+
</discussion>
67+
68+
<resolution>
69+
<p>
70+
This wording is relative to <paper num="N5008"/>.
71+
</p>
72+
73+
<ol>
74+
<li><p>Modify <sref ref="[alg.unique]"/> as indicated:</p>
75+
<blockquote>
76+
6. Let `pred` be `equal_to{}` for the overloads with no parameter `pred`,
77+
and let <i>E</i> be
78+
<ol style="list-style-type: none">
79+
<li> (6.1)
80+
&mdash; <code>bool(pred(<del>*i,</del> *(i - 1))<ins>, *i</ins>)</code>
81+
for the overloads in namespace `std`;
82+
</li>
83+
<li>(6.2)
84+
&mdash; <code>bool(invoke(comp, <del>invoke(proj, *i),</del>
85+
invoke(proj, *(i - 1))<ins>, invoke(proj, *i)</ins>))</code>
86+
for the overloads in namespace `ranges`.
87+
</li>
88+
</ol>
89+
</blockquote>
90+
</li>
91+
</ol>
92+
</resolution>
93+
94+
</issue>

0 commit comments

Comments
 (0)