Skip to content

Commit 5f22bb6

Browse files
committed
Fix infinite ranges and prepare LWG issue
1 parent 624f273 commit 5f22bb6

File tree

2 files changed

+39
-51
lines changed

2 files changed

+39
-51
lines changed

stl/inc/algorithm

Lines changed: 39 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2226,13 +2226,13 @@ namespace ranges {
22262226
// clang-format off
22272227
template <input_iterator _It1, sentinel_for<_It1> _Se1, input_iterator _It2, sentinel_for<_It2> _Se2,
22282228
class _Pr = ranges::equal_to, class _Pj1 = identity, class _Pj2 = identity>
2229-
requires indirectly_comparable<_It1, _It2, _Pr, _Pj1, _Pj2>
2229+
requires (indirectly_comparable<_It1, _It2, _Pr, _Pj1, _Pj2> // Per LWG-issue unnumbered as of 17.09.2021
2230+
&& !(same_as<_Se1, unreachable_sentinel_t> && same_as<_Se2, unreachable_sentinel_t>))
22302231
_NODISCARD constexpr bool operator()(_It1 _First1, _Se1 _Last1, _It2 _First2, _Se2 _Last2, _Pr _Pred = {},
22312232
_Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const {
22322233
// clang-format on
22332234
_Adl_verify_range(_First1, _Last1);
22342235
_Adl_verify_range(_First2, _Last2);
2235-
22362236
if constexpr (same_as<_Se2, unreachable_sentinel_t>) {
22372237
return false;
22382238
}
@@ -2261,7 +2261,9 @@ namespace ranges {
22612261
// clang-format off
22622262
template <input_range _Rng1, input_range _Rng2, class _Pr = ranges::equal_to, class _Pj1 = identity,
22632263
class _Pj2 = identity>
2264-
requires indirectly_comparable<iterator_t<_Rng1>, iterator_t<_Rng2>, _Pr, _Pj1, _Pj2>
2264+
requires (indirectly_comparable<iterator_t<_Rng1>, iterator_t<_Rng2>, _Pr, _Pj1, _Pj2>
2265+
&& !(same_as<sentinel_t<_Rng1>, unreachable_sentinel_t>
2266+
&& same_as<sentinel_t<_Rng2>, unreachable_sentinel_t>)) // Per LWG-issue unnumbered as of 17.09.2021
22652267
_NODISCARD constexpr bool operator()(
22662268
_Rng1&& _Range1, _Rng2&& _Range2, _Pr _Pred = {}, _Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const {
22672269
// clang-format on
@@ -2301,74 +2303,67 @@ namespace ranges {
23012303
requires (forward_iterator<_It1> || sized_sentinel_for<_Se1, _It1>)
23022304
&& (forward_iterator<_It2> || sized_sentinel_for<_Se2, _It2>)
23032305
&& indirectly_comparable<_It1, _It2, _Pr, _Pj1, _Pj2>
2306+
&& (!same_as<_Se1, unreachable_sentinel_t>) // Per LWG-issue unnumbered as of 17.09.2021
23042307
_NODISCARD constexpr bool operator()(_It1 _First1, _Se1 _Last1, _It2 _First2, _Se2 _Last2, _Pr _Pred = {},
23052308
_Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const {
23062309
// clang-format on
23072310
_Adl_verify_range(_First1, _Last1);
23082311
_Adl_verify_range(_First2, _Last2);
2312+
if constexpr (same_as<_Se2, unreachable_sentinel_t>) {
2313+
return false;
2314+
}
23092315

23102316
auto _UFirst1 = _Get_unwrapped(_STD move(_First1));
23112317
auto _ULast1 = _Get_unwrapped(_STD move(_Last1));
23122318
auto _UFirst2 = _Get_unwrapped(_STD move(_First2));
23132319
auto _ULast2 = _Get_unwrapped(_STD move(_Last2));
2314-
if constexpr (same_as<_Se1, unreachable_sentinel_t> && same_as<_Se2, unreachable_sentinel_t>) {
2315-
return _Equal_4(_STD move(_UFirst1), _STD move(_ULast1), _STD move(_UFirst2), _STD move(_ULast2),
2316-
_Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2));
2317-
} else if constexpr (same_as<_Se1, unreachable_sentinel_t> || same_as<_Se2, unreachable_sentinel_t>) {
2318-
return false;
2319-
} else {
2320-
iter_difference_t<_It1> _Count1;
2321-
if constexpr (sized_sentinel_for<_Se1, _It1>) { // TRANSITION, LWG-3392
2322-
_Count1 = _ULast1 - _UFirst1;
2323-
} else {
2324-
_Count1 = _RANGES distance(_UFirst1, _ULast1);
2325-
}
23262320

2327-
iter_difference_t<_It2> _Count2;
2328-
if constexpr (sized_sentinel_for<_Se2, _It2>) { // TRANSITION, LWG-3392
2329-
_Count2 = _ULast2 - _UFirst2;
2330-
} else {
2331-
_Count2 = _RANGES distance(_UFirst2, _ULast2);
2332-
}
2321+
iter_difference_t<_It1> _Count1;
2322+
if constexpr (sized_sentinel_for<_Se1, _It1>) { // TRANSITION, LWG-3392
2323+
_Count1 = _ULast1 - _UFirst1;
2324+
} else {
2325+
_Count1 = _RANGES distance(_UFirst1, _ULast1);
2326+
}
23332327

2334-
if (_Count2 > _Count1) {
2335-
return false;
2336-
}
2328+
iter_difference_t<_It2> _Count2;
2329+
if constexpr (sized_sentinel_for<_Se2, _It2>) { // TRANSITION, LWG-3392
2330+
_Count2 = _ULast2 - _UFirst2;
2331+
} else {
2332+
_Count2 = _RANGES distance(_UFirst2, _ULast2);
2333+
}
23372334

2338-
_RANGES advance(_UFirst1, static_cast<iter_difference_t<_It1>>(_Count1 - _Count2));
2339-
return _RANGES _Equal_count(_STD move(_UFirst1), _STD move(_UFirst2),
2340-
static_cast<iter_difference_t<_It1>>(_Count2), _Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2));
2335+
if (_Count2 > _Count1) {
2336+
return false;
23412337
}
2338+
2339+
_RANGES advance(_UFirst1, static_cast<iter_difference_t<_It1>>(_Count1 - _Count2));
2340+
return _RANGES _Equal_count(_STD move(_UFirst1), _STD move(_UFirst2),
2341+
static_cast<iter_difference_t<_It1>>(_Count2), _Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2));
23422342
}
23432343

23442344
// clang-format off
23452345
template <input_range _Rng1, input_range _Rng2, class _Pr = ranges::equal_to, class _Pj1 = identity,
23462346
class _Pj2 = identity>
23472347
requires (forward_range<_Rng1> || sized_range<_Rng1>) && (forward_range<_Rng2> || sized_range<_Rng2>)
23482348
&& indirectly_comparable<iterator_t<_Rng1>, iterator_t<_Rng2>, _Pr, _Pj1, _Pj2>
2349+
&& (!same_as<sentinel_t<_Rng1>, unreachable_sentinel_t>) // Per LWG-issue unnumbered as of 17.09.2021
23492350
_NODISCARD constexpr bool operator()(
23502351
_Rng1&& _Range1, _Rng2&& _Range2, _Pr _Pred = {}, _Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const {
23512352
// clang-format on
2352-
if constexpr (same_as<sentinel_t<_Rng1>, unreachable_sentinel_t> //
2353-
&& same_as<sentinel_t<_Rng2>, unreachable_sentinel_t>)
2354-
return _Equal_4(_Ubegin(_Range1), _Uend(_Range1), _Ubegin(_Range2), _Uend(_Range2), _Pass_fn(_Pred),
2355-
_Pass_fn(_Proj1), _Pass_fn(_Proj2));
2356-
else if constexpr (same_as<sentinel_t<_Rng1>, unreachable_sentinel_t> //
2357-
|| same_as<sentinel_t<_Rng2>, unreachable_sentinel_t>) {
2353+
if constexpr (same_as<sentinel_t<_Rng2>, unreachable_sentinel_t>) {
23582354
return false;
2359-
} else {
2360-
const range_difference_t<_Rng1> _Count1 = _RANGES distance(_Range1);
2361-
const range_difference_t<_Rng2> _Count2 = _RANGES distance(_Range2);
2362-
if (_Count2 > _Count1) {
2363-
return false;
2364-
}
2355+
}
23652356

2366-
auto _UFirst1 = _Ubegin(_Range1);
2367-
_RANGES advance(_UFirst1, static_cast<range_difference_t<_Rng1>>(_Count1 - _Count2));
2368-
return _RANGES _Equal_count(_STD move(_UFirst1), _Ubegin(_Range2),
2369-
static_cast<range_difference_t<_Rng1>>(_Count2), _Pass_fn(_Pred), _Pass_fn(_Proj1),
2370-
_Pass_fn(_Proj2));
2357+
const range_difference_t<_Rng1> _Count1 = _RANGES distance(_Range1);
2358+
const range_difference_t<_Rng2> _Count2 = _RANGES distance(_Range2);
2359+
if (_Count2 > _Count1) {
2360+
return false;
23712361
}
2362+
2363+
auto _UFirst1 = _Ubegin(_Range1);
2364+
_RANGES advance(_UFirst1, static_cast<range_difference_t<_Rng1>>(_Count1 - _Count2));
2365+
return _RANGES _Equal_count(_STD move(_UFirst1), _Ubegin(_Range2),
2366+
static_cast<range_difference_t<_Rng1>>(_Count2), _Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2));
23722367
}
23732368
};
23742369

tests/std/tests/P1659R3_ranges_alg_ends_with/test.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@ constexpr void smoke_test() {
3131
assert(!no_match2);
3232
}
3333
{ // Validate infinite ranges
34-
const same_as<bool> auto infinite_haystack = ends_with(views::iota(0), views::iota(0, 5));
35-
assert(!infinite_haystack);
36-
3734
const same_as<bool> auto infinite_needle = ends_with(views::iota(0, 5), views::iota(0));
3835
assert(!infinite_needle);
3936
}
@@ -51,10 +48,6 @@ constexpr void smoke_test() {
5148
assert(!no_match2);
5249
}
5350
{ // Validate unreachable sentinel
54-
const same_as<bool> auto unreachable_haystack = ends_with(
55-
haystack.begin(), unreachable_sentinel, needle.begin(), needle.end(), equal_to{}, get_first, get_second);
56-
assert(!unreachable_haystack);
57-
5851
const same_as<bool> auto unreachable_needle = ends_with(
5952
haystack.begin(), haystack.end(), needle.begin(), unreachable_sentinel, equal_to{}, get_first, get_second);
6053
assert(!unreachable_needle);

0 commit comments

Comments
 (0)