ranges::equal
and ranges::is_permutation
should short-circuit for sized_ranges
Section: 26.6.13 [alg.equal], 26.6.14 [alg.is.permutation] Status: C++23 Submitter: Tim Song Opened: 2021-06-03 Last modified: 2023-11-22
Priority: Not Prioritized
View all other issues in [alg.equal].
View all issues with C++23 status.
Discussion:
ranges::equal
and ranges::is_permutation
are currently only required
to short-circuit on different sizes if the iterator and sentinel of the two ranges
pairwise model sized_sentinel_for
. They should also short-circuit if the ranges are sized.
[2021-06-23; Reflector poll]
Set status to Tentatively Ready after five votes in favour during reflector poll.
[2021-10-14 Approved at October 2021 virtual plenary. Status changed: Voting → WP.]
Proposed resolution:
This wording is relative to N4885.
Modify 26.6.13 [alg.equal] as indicated:
template<class InputIterator1, class InputIterator2> constexpr bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2); […] template<class InputIterator1, class InputIterator2, class BinaryPredicate> constexpr bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred); […] template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr bool ranges::equal(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr bool ranges::equal(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {});[…]
-3- Complexity: Ifthe types of:first1
,last1
,first2
, andlast2
(3.1) — the types of
first1
,last1
,first2
, andlast2
meet the Cpp17RandomAccessIterator requirements (24.3.5.7 [random.access.iterators]) andlast1 - first1 != last2 - first2
for the overloads in namespacestd
;(3.2) — the types of
first1
,last1
,first2
, andlast2
pairwise modelsized_sentinel_for
(24.3.4.8 [iterator.concept.sizedsentinel]) andlast1 - first1 != last2 - first2
for the first overloadsin namespaceranges
,(3.3) —
R1
andR2
each modelsized_range
andranges::distance(r1) != ranges::distance(r2)
for the second overload in namespaceranges
,
andthen no applications of the corresponding predicate and each projection; otherwise, […]last1 - first1 != last2 - first2
,
Modify 26.6.14 [alg.is.permutation] as indicated:
template<forward_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2, class Proj1 = identity, class Proj2 = identity, indirect_equivalence_relation<projected<I1, Proj1>, projected<I2, Proj2>> Pred = ranges::equal_to> constexpr bool ranges::is_permutation(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<forward_range R1, forward_range R2, class Proj1 = identity, class Proj2 = identity, indirect_equivalence_relation<projected<iterator_t<R1>, Proj1>, projected<iterator_t<R2>, Proj2>> Pred = ranges::equal_to> constexpr bool ranges::is_permutation(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {});[…]
-7- Complexity: No applications of the corresponding predicate and projections if:
(7.1) — for the first overload,
(7.1.1) —
S1
andI1
modelsized_sentinel_for<S1, I1>
,(7.1.2) —
S2
andI2
modelsized_sentinel_for<S2, I2>
, and(7.1.3) —
last1 - first1 != last2 - first2
.;(7.2) — for the second overload,
R1
andR2
each modelsized_range
, andranges::distance(r1) != ranges::distance(r2)
.Otherwise, exactly
last1 - first1
applications of the corresponding predicate and projections ifranges::equal(first1, last1, first2, last2, pred, proj1, proj2)
would returntrue
; otherwise, at worst 𝒪(N2
), whereN
has the valuelast1 - first1
.