unique_copy passes arguments to its predicate backwardsSection: 26.7.9 [alg.unique] Status: New Submitter: Jonathan Wakely Opened: 2025-05-29 Last modified: 2025-05-29
Priority: Not Prioritized
View other active issues in [alg.unique].
View all other issues in [alg.unique].
View all issues with New status.
Discussion:
For the unique algorithms, 26.7.9 [alg.unique] p1 says:
1. Letpredbeequal_to{}for the overloads with no parameterpred, and let E be
- (1.1) —
bool(pred(*(i - 1), *i))for the overloads in namespacestd;- (1.2) —
bool(invoke(comp, invoke(proj, *(i - 1)), invoke(proj, *i)))for the overloads in namespaceranges.
However for the unique_copy algorithms, 26.7.9 [alg.unique] p6 says
that the arguments *i and *(i-1) should be reversed:
6. Letpredbeequal_to{}for the overloads with no parameterpred, and let E be
- (6.1) —
bool(pred(*i, *(i - 1)))for the overloads in namespacestd;- (6.2) —
bool(invoke(comp, invoke(proj, *i), invoke(proj, *(i - 1))))for the overloads in namespaceranges.
This reversed order is consistent with the documentation for
SGI STL unique_copy,
although the docs for
SGI STL unique
show reversed arguments too, and the C++ standard doesn't match that.
A survey of known implementations shows that all three of libstdc++, libc++,
and MSVC STL use the pred(*(i - 1), *i) order for all of std::unique,
std::unique_copy, ranges::unique, and ranges::unique_copy. The range-v3
library did the same, and even the SGI STL did too (despite what its docs said).
Only two implementations were found which match the spec and use a different
argument order for unique and unique_copy, Casey Carter's (cmcstl2) and
Fraser Gordon's.
In the absence of any known rationale for unique and unique_copy to differ,
it seems sensible to make unique_copy more consistent with unique
(and with the majority of implementations stretching back three decades).
Proposed resolution:
This wording is relative to N5008.
Modify 26.7.9 [alg.unique] as indicated:
6. Letpredbeequal_to{}for the overloads with no parameterpred, and let E be
- (6.1) —
bool(pred(for the overloads in namespace*i,*(i - 1)), *i)std;- (6.2) —
bool(invoke(comp,for the overloads in namespaceinvoke(proj, *i),invoke(proj, *(i - 1)), invoke(proj, *i)))ranges.