Check if `find_last` can find anything (#4561)

Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
This commit is contained in:
Alex Guteniev 2024-04-10 01:38:03 +03:00 коммит произвёл GitHub
Родитель 51b1a07a51
Коммит d0995ffb4a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
3 изменённых файлов: 237 добавлений и 4 удалений

Просмотреть файл

@ -3028,7 +3028,12 @@ namespace ranges {
if constexpr (is_same_v<_Pj, identity> && _Vector_alg_in_find_is_safe<_It, _Ty>
&& sized_sentinel_for<_Se, _It>) {
if (!_STD is_constant_evaluated()) {
const auto _Count = _Last - _First;
const auto _Count = _Last - _First;
if (!_STD _Could_compare_equal_to_value_type<_It>(_Value)) {
return {_First + _Count, _First + _Count};
}
const auto _First_ptr = _STD _To_address(_First);
const auto _Last_ptr = _First_ptr + _Count;

Просмотреть файл

@ -2,3 +2,6 @@
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
RUNALL_INCLUDE ..\usual_matrix.lst
RUNALL_CROSSLIST
* PM_CL=""
* PM_CL="/D_USE_STD_VECTOR_ALGORITHMS=0"

Просмотреть файл

@ -55,14 +55,23 @@ void test_limit_check_elements_impl() {
if constexpr (is_signed_v<ValueType>) {
if constexpr (numeric_limits<ValueType>::min() < min_val) {
assert(find(begin(sc), end(sc), ValueType{ValueType{min_val} - 1}) == end(sc));
#if _HAS_CXX23
assert(ranges::find_last(sc, ValueType{ValueType{min_val} - 1}).begin() == end(sc));
#endif // _HAS_CXX23
}
if constexpr (sizeof(ElementType) <= sizeof(ValueType)) {
assert(find(begin(sc), end(sc), ValueType{min_val}) == begin(sc));
#if _HAS_CXX23
assert(ranges::find_last(sc, ValueType{min_val}).begin() == begin(sc));
#endif // _HAS_CXX23
}
assert(find(begin(sc), end(sc), ValueType{-1}) == begin(sc) + 4);
assert(find(begin(sc), end(sc), ValueType{-1}) == begin(sc) + 4);
assert(count(begin(sc), end(sc), ValueType{-1}) == 2);
#if _HAS_CXX23
assert(ranges::find_last(sc, ValueType{-1}).begin() == begin(sc) + 5);
#endif // _HAS_CXX23
} else {
constexpr auto max_vt = numeric_limits<ValueType>::max();
if constexpr (ElementType{-1} == max_vt) {
@ -72,23 +81,42 @@ void test_limit_check_elements_impl() {
assert(count(begin(sc), end(sc), max_vt) == 2);
assert(count(begin(sc), end(sc), max_vt - 1) == 1);
#if _HAS_CXX23
assert(ranges::find_last(sc, max_vt).begin() == begin(sc) + 5);
assert(ranges::find_last(sc, max_vt - 1).begin() == begin(sc) + 3);
#endif // _HAS_CXX23
} else {
assert(find(begin(sc), end(sc), max_vt) == end(sc));
assert(find(begin(sc), end(sc), max_vt - 1) == end(sc));
assert(count(begin(sc), end(sc), max_vt) == 0);
assert(count(begin(sc), end(sc), max_vt - 1) == 0);
#if _HAS_CXX23
assert(ranges::find_last(sc, max_vt).begin() == end(sc));
assert(ranges::find_last(sc, max_vt - 1).begin() == end(sc));
#endif // _HAS_CXX23
}
}
assert(count(begin(sc), end(sc), ValueType{0}) == 1);
assert(find(begin(sc), end(sc), ValueType{0}) == begin(sc) + 6);
assert(find(begin(sc), end(sc), ValueType{5}) == end(sc));
assert(count(begin(sc), end(sc), ValueType{0}) == 1);
assert(count(begin(sc), end(sc), ValueType{5}) == 0);
#if _HAS_CXX23
assert(ranges::find_last(sc, ValueType{0}).begin() == begin(sc) + 6);
assert(ranges::find_last(sc, ValueType{5}).begin() == end(sc));
#endif // _HAS_CXX23
if constexpr (sizeof(ElementType) <= sizeof(ValueType)) {
assert(find(begin(sc), end(sc), ValueType{max_val}) == begin(sc) + 12);
assert(count(begin(sc), end(sc), ValueType{max_val}) == 1);
#if _HAS_CXX23
assert(ranges::find_last(sc, ValueType{max_val}).begin() == begin(sc) + 12);
#endif // _HAS_CXX23
if constexpr (sizeof(ElementType) < sizeof(ValueType)) {
assert(find(begin(sc), end(sc), ValueType{ValueType{max_val} + 1}) == end(sc));
@ -96,6 +124,11 @@ void test_limit_check_elements_impl() {
assert(count(begin(sc), end(sc), ValueType{ValueType{max_val} + 1}) == 0);
assert(count(begin(sc), end(sc), ValueType{umax_val}) == 0);
#if _HAS_CXX23
assert(ranges::find_last(sc, ValueType{ValueType{max_val} + 1}).begin() == end(sc));
assert(ranges::find_last(sc, ValueType{umax_val}).begin() == end(sc));
#endif // _HAS_CXX23
}
}
} else {
@ -107,6 +140,11 @@ void test_limit_check_elements_impl() {
assert(find(begin(uc), end(uc), ValueType{0}) == begin(uc));
assert(find(begin(uc), end(uc), ValueType{2}) == begin(uc) + 3);
assert(find(begin(uc), end(uc), ValueType{6}) == end(uc));
#if _HAS_CXX23
assert(ranges::find_last(uc, ValueType{0}).begin() == begin(uc));
assert(ranges::find_last(uc, ValueType{2}).begin() == begin(uc) + 3);
assert(ranges::find_last(uc, ValueType{6}).begin() == end(uc));
#endif // _HAS_CXX23
if constexpr (is_signed_v<ValueType>) {
if constexpr (ValueType{-1} == max_val) {
@ -116,12 +154,20 @@ void test_limit_check_elements_impl() {
assert(count(begin(uc), end(uc), ValueType{-1}) == 1);
assert(count(begin(uc), end(uc), ValueType{-2}) == 1);
#if _HAS_CXX23
assert(ranges::find_last(uc, ValueType{-1}).begin() == begin(uc) + 6);
assert(ranges::find_last(uc, ValueType{-2}).begin() == begin(uc) + 5);
#endif // _HAS_CXX23
} else {
assert(find(begin(uc), end(uc), ValueType{-1}) == end(uc));
assert(find(begin(uc), end(uc), ValueType{-2}) == end(uc));
assert(count(begin(uc), end(uc), ValueType{-1}) == 0);
assert(count(begin(uc), end(uc), ValueType{-2}) == 0);
#if _HAS_CXX23
assert(ranges::find_last(uc, ValueType{-1}).begin() == end(uc));
assert(ranges::find_last(uc, ValueType{-2}).begin() == end(uc));
#endif // _HAS_CXX23
}
}
@ -129,10 +175,24 @@ void test_limit_check_elements_impl() {
assert(find(begin(uc), end(uc), ValueType{max_val - 3}) == end(uc));
assert(find(begin(uc), end(uc), ValueType{max_val - 2}) == begin(uc) + 4);
assert(find(begin(uc), end(uc), ValueType{max_val}) == begin(uc) + 6);
#if _HAS_CXX23
assert(ranges::find_last(uc, ValueType{max_val - 3}).begin() == end(uc));
assert(ranges::find_last(uc, ValueType{max_val - 2}).begin() == begin(uc) + 4);
assert(ranges::find_last(uc, ValueType{max_val}).begin() == begin(uc) + 6);
#endif // _HAS_CXX23
if constexpr (max_val < max_vt) {
assert(find(begin(uc), end(uc), ValueType{ValueType{max_val} + 1}) == end(uc));
#if _HAS_CXX23
assert(ranges::find_last(uc, ValueType{ValueType{max_val} + 1}).begin() == end(uc));
#endif // _HAS_CXX23
if constexpr (sizeof(ElementType) < sizeof(ValueType)) {
assert(find(begin(uc), end(uc), max_vt) == end(uc));
#if _HAS_CXX23
assert(ranges::find_last(uc, max_vt).begin() == end(uc));
#endif // _HAS_CXX23
}
}
}
@ -180,6 +240,12 @@ int main() {
assert(count(v.cbegin(), v.cend(), 33) == 1);
assert(count(v.cbegin(), v.cend(), 44) == 2);
assert(count(v.cbegin(), v.cend(), 255) == 0);
#if _HAS_CXX23
assert(ranges::find_last(v, 33).begin() - v.begin() == 1);
assert(ranges::find_last(v, -1).begin() - v.begin() == 2);
assert(ranges::find_last(v, 255).begin() - v.begin() == 6);
#endif // _HAS_CXX23
}
@ -199,6 +265,11 @@ int main() {
assert(count(l.begin(), l.end(), 44) == 2);
assert(count(l.begin(), l.end(), 17) == 0);
#if _HAS_CXX23
assert(ranges::find_last(l, 44).begin() == next(l.begin(), 4));
assert(ranges::find_last(l, 17).begin() == l.end());
#endif // _HAS_CXX23
}
{ // Optimization inapplicable due to bogus element type and bogus value type
@ -215,6 +286,11 @@ int main() {
assert(count(v.begin(), v.end(), "cute") == 2);
assert(count(v.begin(), v.end(), "zombies") == 0);
#if _HAS_CXX23
assert(ranges::find_last(v, "fluffy").begin() == v.begin() + 2);
assert(ranges::find_last(v, "zombies").begin() == v.end());
#endif // _HAS_CXX23
}
{
@ -237,6 +313,11 @@ int main() {
assert(count(v.begin(), v.end(), 0xAABBCCDDUL) == 1);
assert(count(v.begin(), v.end(), 0x11UL) == 0);
#if _HAS_CXX23
assert(ranges::find_last(v, 0xAABBCCDDUL).begin() == v.begin() + 2);
assert(ranges::find_last(v, 0x11UL).begin() == v.end());
#endif // _HAS_CXX23
}
{ // Optimization inapplicable due to bogus value type (although the element type is good)
@ -280,6 +361,11 @@ int main() {
assert(count(vc.cbegin(), vc.cend(), 'o') == 2);
assert(count(vc.cbegin(), vc.cend(), 'X') == 0);
#if _HAS_CXX23
assert(ranges::find_last(vc, 'o').begin() == vc.begin() + 4);
assert(ranges::find_last(vc, 'X').begin() == vc.end());
#endif // _HAS_CXX23
}
{ // Test optimized element types.
@ -307,6 +393,15 @@ int main() {
assert(find(vsc.cbegin(), vsc.cend(), -128) == vsc.cbegin() + 3);
assert(find(vsc.cbegin(), vsc.cend(), 127) == vsc.cbegin() + 4);
assert(find(vsc.cbegin(), vsc.cend(), 255) == vsc.cend());
#if _HAS_CXX23
assert(ranges::find_last(vsc, 17).begin() == vsc.begin());
assert(ranges::find_last(vsc, 29).begin() == vsc.begin() + 1);
assert(ranges::find_last(vsc, -1).begin() == vsc.begin() + 2);
assert(ranges::find_last(vsc, -128).begin() == vsc.begin() + 3);
assert(ranges::find_last(vsc, 127).begin() == vsc.begin() + 4);
assert(ranges::find_last(vsc, 255).begin() == vsc.end());
#endif // _HAS_CXX23
}
{ // Test optimized element types.
@ -328,6 +423,12 @@ int main() {
assert(find(vuc.cbegin(), vuc.cend(), 47) == vuc.cbegin() + 2);
assert(find(vuc.cbegin(), vuc.cend(), 255) == vuc.cbegin() + 4);
assert(find(vuc.cbegin(), vuc.cend(), -1) == vuc.cend());
#if _HAS_CXX23
assert(ranges::find_last(vuc, 47).begin() == vuc.begin() + 2);
assert(ranges::find_last(vuc, 255).begin() == vuc.begin() + 4);
assert(ranges::find_last(vuc, -1).begin() == vuc.end());
#endif // _HAS_CXX23
}
@ -353,6 +454,26 @@ int main() {
assert(find(begin(arr), end(arr), false) == begin(arr) + 2);
assert(find(begin(arr), end(arr), true) == end(arr));
#if _HAS_CXX23
assert(ranges::find_last(arr, static_cast<signed char>(30)).begin() == begin(arr) + 4);
assert(ranges::find_last(arr, static_cast<short>(30)).begin() == begin(arr) + 4);
assert(ranges::find_last(arr, static_cast<int>(30)).begin() == begin(arr) + 4);
assert(ranges::find_last(arr, static_cast<long>(30)).begin() == begin(arr) + 4);
assert(ranges::find_last(arr, static_cast<long long>(30)).begin() == begin(arr) + 4);
assert(ranges::find_last(arr, static_cast<unsigned char>(30)).begin() == begin(arr) + 4);
assert(ranges::find_last(arr, static_cast<unsigned short>(30)).begin() == begin(arr) + 4);
assert(ranges::find_last(arr, static_cast<unsigned int>(30)).begin() == begin(arr) + 4);
assert(ranges::find_last(arr, static_cast<unsigned long>(30)).begin() == begin(arr) + 4);
assert(ranges::find_last(arr, static_cast<unsigned long long>(30)).begin() == begin(arr) + 4);
assert(ranges::find_last(arr, static_cast<char>(30)).begin() == begin(arr) + 4);
assert(ranges::find_last(arr, static_cast<wchar_t>(30)).begin() == begin(arr) + 4);
assert(ranges::find_last(arr, false).begin() == begin(arr) + 2);
assert(ranges::find_last(arr, true).begin() == end(arr));
#endif // _HAS_CXX23
}
// Test limit checks.
@ -395,6 +516,26 @@ int main() {
assert(find(begin(sc), end(sc), 0xFFFFFFFFFFFFFF7FULL) == end(sc));
assert(find(begin(sc), end(sc), 0xFFFFFFFFFFFFFF00ULL) == end(sc));
#if _HAS_CXX23
assert(ranges::find_last(sc, static_cast<unsigned short>(0xFFFF)).begin() == end(sc));
assert(ranges::find_last(sc, 0xFFFFFFFFUL).begin() == begin(sc) + 4);
assert(ranges::find_last(sc, 0xFFFFFFFEUL).begin() == begin(sc) + 3);
assert(ranges::find_last(sc, 0xFFFFFFAAUL).begin() == end(sc));
assert(ranges::find_last(sc, 0xFFFFFF81UL).begin() == begin(sc) + 1);
assert(ranges::find_last(sc, 0xFFFFFF80UL).begin() == begin(sc));
assert(ranges::find_last(sc, 0xFFFFFF7FUL).begin() == end(sc));
assert(ranges::find_last(sc, 0xFFFFFF00UL).begin() == end(sc));
assert(ranges::find_last(sc, 0xFFFFFFFFFFFFFFFFULL).begin() == begin(sc) + 4);
assert(ranges::find_last(sc, 0xFFFFFFFFFFFFFFFEULL).begin() == begin(sc) + 3);
assert(ranges::find_last(sc, 0xFFFFFFFFFFFFFFAAULL).begin() == end(sc));
assert(ranges::find_last(sc, 0xFFFFFFFFFFFFFF81ULL).begin() == begin(sc) + 1);
assert(ranges::find_last(sc, 0xFFFFFFFFFFFFFF80ULL).begin() == begin(sc));
assert(ranges::find_last(sc, 0xFFFFFFFFFFFFFF7FULL).begin() == end(sc));
assert(ranges::find_last(sc, 0xFFFFFFFFFFFFFF00ULL).begin() == end(sc));
#endif // _HAS_CXX23
const short ss[] = {-32768, -32767, -32766, -2, -1, 0, 1, 2, 32765, 32766, 32767};
STATIC_ASSERT(static_cast<short>(-1) != static_cast<unsigned short>(0xFFFF));
@ -421,6 +562,26 @@ int main() {
assert(find(begin(ss), end(ss), 0xFFFFFFFFFFFF7FFFULL) == end(ss));
assert(find(begin(ss), end(ss), 0xFFFFFFFFFFFF0000ULL) == end(ss));
#if _HAS_CXX23
assert(ranges::find_last(ss, static_cast<unsigned short>(0xFFFF)).begin() == end(ss));
assert(ranges::find_last(ss, 0xFFFFFFFFUL).begin() == begin(ss) + 4);
assert(ranges::find_last(ss, 0xFFFFFFFEUL).begin() == begin(ss) + 3);
assert(ranges::find_last(ss, 0xFFFFAAAAUL).begin() == end(ss));
assert(ranges::find_last(ss, 0xFFFF8001UL).begin() == begin(ss) + 1);
assert(ranges::find_last(ss, 0xFFFF8000UL).begin() == begin(ss));
assert(ranges::find_last(ss, 0xFFFF7FFFUL).begin() == end(ss));
assert(ranges::find_last(ss, 0xFFFF0000UL).begin() == end(ss));
assert(ranges::find_last(ss, 0xFFFFFFFFFFFFFFFFULL).begin() == begin(ss) + 4);
assert(ranges::find_last(ss, 0xFFFFFFFFFFFFFFFEULL).begin() == begin(ss) + 3);
assert(ranges::find_last(ss, 0xFFFFFFFFFFFFAAAAULL).begin() == end(ss));
assert(ranges::find_last(ss, 0xFFFFFFFFFFFF8001ULL).begin() == begin(ss) + 1);
assert(ranges::find_last(ss, 0xFFFFFFFFFFFF8000ULL).begin() == begin(ss));
assert(ranges::find_last(ss, 0xFFFFFFFFFFFF7FFFULL).begin() == end(ss));
assert(ranges::find_last(ss, 0xFFFFFFFFFFFF0000ULL).begin() == end(ss));
#endif // _HAS_CXX23
// No longer integral promotions, still repeat the applicable part once to be sure
const long sl[] = {long_min, long_min + 1, long_min + 2, -2, -1, 0, 1, 2, long_max - 2, long_max - 1, long_max};
@ -446,6 +607,24 @@ int main() {
assert(find(begin(sl), end(sl), 0xFFFFFFFF80000000ULL) == begin(sl));
assert(find(begin(sl), end(sl), 0xFFFFFFFF7FFFFFFFULL) == end(sl));
assert(find(begin(sl), end(sl), 0xFFFFFFFF00000000ULL) == end(sl));
#if _HAS_CXX23
assert(ranges::find_last(sl, static_cast<unsigned short>(0xFFFF)).begin() == end(sl));
assert(ranges::find_last(sl, 0xFFFFFFFFUL).begin() == begin(sl) + 4);
assert(ranges::find_last(sl, 0xFFFFFFFEUL).begin() == begin(sl) + 3);
assert(ranges::find_last(sl, 0xAAAAAAAAUL).begin() == end(sl));
assert(ranges::find_last(sl, 0x80000001UL).begin() == begin(sl) + 1);
assert(ranges::find_last(sl, 0x80000000UL).begin() == begin(sl));
assert(ranges::find_last(sl, 0xFFFFFFFFFFFFFFFFULL).begin() == begin(sl) + 4);
assert(ranges::find_last(sl, 0xFFFFFFFFFFFFFFFEULL).begin() == begin(sl) + 3);
assert(ranges::find_last(sl, 0xFFFFFFFFAAAAAAAAULL).begin() == end(sl));
assert(ranges::find_last(sl, 0xFFFFFFFF80000001ULL).begin() == begin(sl) + 1);
assert(ranges::find_last(sl, 0xFFFFFFFF80000000ULL).begin() == begin(sl));
assert(ranges::find_last(sl, 0xFFFFFFFF7FFFFFFFULL).begin() == end(sl));
assert(ranges::find_last(sl, 0xFFFFFFFF00000000ULL).begin() == end(sl));
#endif // _HAS_CXX23
}
{ // unsigned int == int, weird conversions yay! (GH-3244)
@ -456,6 +635,14 @@ int main() {
assert(find(begin(ui), end(ui), 3) == end(ui));
assert(find(begin(ui), end(ui), -2) == begin(ui) + 4);
assert(find(begin(ui), end(ui), -1) == begin(ui) + 5);
#if _HAS_CXX23
assert(ranges::find_last(ui, 0).begin() == begin(ui));
assert(ranges::find_last(ui, 2).begin() == begin(ui) + 2);
assert(ranges::find_last(ui, 3).begin() == end(ui));
assert(ranges::find_last(ui, -2).begin() == begin(ui) + 4);
assert(ranges::find_last(ui, -1).begin() == begin(ui) + 5);
#endif // _HAS_CXX23
}
{ // Test bools
@ -470,6 +657,12 @@ int main() {
assert(count(begin(arr), end(arr), false) == 2);
assert(count(begin(arr), end(arr), true) == 4);
assert(count(begin(arr), end(arr), 2) == 0);
#if _HAS_CXX23
assert(ranges::find_last(arr, false).begin() == begin(arr) + 5);
assert(ranges::find_last(arr, true).begin() == begin(arr) + 4);
assert(ranges::find_last(arr, 2).begin() == end(arr));
#endif // _HAS_CXX23
}
{ // Test pointers
@ -508,6 +701,22 @@ int main() {
assert(count(begin(arr), end(arr), static_cast<const char*>(nullptr)) == 1);
assert(count(begin(arr), end(arr), nullptr) == 1);
#if _HAS_CXX23
assert(ranges::find_last(arr, s).begin() == begin(arr) + 4);
assert(ranges::find_last(arr, const_cast<char*>(s)).begin() == begin(arr) + 4);
assert(ranges::find_last(arr, const_cast<volatile char*>(s)).begin() == begin(arr) + 4);
assert(ranges::find_last(arr, s + 1).begin() == begin(arr) + 2);
assert(ranges::find_last(arr, static_cast<const void*>(s + 1)).begin() == begin(arr) + 2);
assert(ranges::find_last(arr, s + 3).begin() == end(arr));
assert(ranges::find_last(arr, static_cast<const void*>(s + 3)).begin() == end(arr));
assert(ranges::find_last(arr, static_cast<const char*>(nullptr)).begin() == begin(arr) + 6);
assert(ranges::find_last(arr, static_cast<const void*>(nullptr)).begin() == begin(arr) + 6);
assert(ranges::find_last(arr, nullptr).begin() == begin(arr) + 6);
#endif // _HAS_CXX23
// const void pointer range
assert(find(begin(arr_void), end(arr_void), s) == begin(arr_void));
assert(find(begin(arr_void), end(arr_void), const_cast<char*>(s)) == begin(arr_void));
@ -528,6 +737,22 @@ int main() {
assert(count(begin(arr_void), end(arr_void), s + 3) == 0);
assert(count(begin(arr_void), end(arr_void), static_cast<const char*>(nullptr)) == 1);
assert(count(begin(arr_void), end(arr_void), nullptr) == 1);
#if _HAS_CXX23
assert(ranges::find_last(arr_void, s).begin() == begin(arr_void) + 4);
assert(ranges::find_last(arr_void, const_cast<char*>(s)).begin() == begin(arr_void) + 4);
assert(ranges::find_last(arr_void, const_cast<volatile char*>(s)).begin() == begin(arr_void) + 4);
assert(ranges::find_last(arr_void, s + 1).begin() == begin(arr_void) + 2);
assert(ranges::find_last(arr_void, static_cast<const void*>(s + 1)).begin() == begin(arr_void) + 2);
assert(ranges::find_last(arr_void, s + 3).begin() == end(arr_void));
assert(ranges::find_last(arr_void, static_cast<const void*>(s + 3)).begin() == end(arr_void));
assert(ranges::find_last(arr_void, static_cast<const char*>(nullptr)).begin() == begin(arr_void) + 6);
assert(ranges::find_last(arr_void, static_cast<const void*>(nullptr)).begin() == begin(arr_void) + 6);
assert(ranges::find_last(arr_void, nullptr).begin() == begin(arr_void) + 6);
#endif // _HAS_CXX23
}
{ // random other checks for _Vector_alg_in_find_is_safe