From d1c1d82bbb02aeb9bee68977dcac7584c041dc10 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 27 Sep 2021 09:57:33 +0300 Subject: [PATCH 01/23] nested exception --- stl/inc/exception | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/stl/inc/exception b/stl/inc/exception index 0643e0be91..e575e4336b 100644 --- a/stl/inc/exception +++ b/stl/inc/exception @@ -363,25 +363,18 @@ template } #ifdef _CPPRTTI -template -void _Rethrow_if_nested(const _Ty* _Ptr, true_type) { // use dynamic_cast - const auto _Nested = dynamic_cast(_Ptr); - - if (_Nested) { - _Nested->rethrow_nested(); - } -} - -template -void _Rethrow_if_nested(const _Ty*, false_type) {} // can't use dynamic_cast - template void rethrow_if_nested(const _Ty& _Arg) { // detect nested_exception inheritance - bool_constant< - is_polymorphic_v<_Ty> && (!is_base_of_v || is_convertible_v<_Ty*, nested_exception*>)> - _Tag; + constexpr bool _Can_use_dynamic_cast = + is_polymorphic_v<_Ty> && (!is_base_of_v || is_convertible_v<_Ty*, nested_exception*>); + + if constexpr (_Can_use_dynamic_cast) { + const auto _Nested = dynamic_cast(_STD addressof(_Arg)); - _Rethrow_if_nested(_STD addressof(_Arg), _Tag); + if (_Nested) { + _Nested->rethrow_nested(); + } + } } #else // _CPPRTTI template From b51d730630879ac577e540d6e7a400a6e41a9e40 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 27 Sep 2021 10:05:12 +0300 Subject: [PATCH 02/23] regex compare --- stl/inc/regex | 50 +++++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/stl/inc/regex b/stl/inc/regex index 61d7a4d868..0e163c9d0a 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -502,43 +502,35 @@ private: }; template -int _Iter_compare3(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, true_type) { - // _Iter_compare for memory buffer ranges - return _Traits_compare<_Traits>( - _First1, static_cast(_Last1 - _First1), _First2, static_cast(_Last2 - _First2)); -} +int _Iter_compare2(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2) { + if constexpr (is_pointer<_FwdIt1>::value && is_pointer<_FwdIt2>::value) { + // _Iter_compare for memory buffer ranges + return _Traits_compare<_Traits>( + _First1, static_cast(_Last1 - _First1), _First2, static_cast(_Last2 - _First2)); + } else { + // _Iter_compare for general ranges + const pair<_FwdIt1, _FwdIt2> _Cmp = _STD mismatch(_First1, _Last1, _First2, _Last2, _Char_traits_eq<_Traits>{}); -template -int _Iter_compare3(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, false_type) { - // _Iter_compare for general ranges - const pair<_FwdIt1, _FwdIt2> _Cmp = _STD mismatch(_First1, _Last1, _First2, _Last2, _Char_traits_eq<_Traits>{}); + if (_Cmp.first == _Last1) { + if (_Cmp.second == _Last2) { + return 0; + } else { + return -1; + } + } - if (_Cmp.first == _Last1) { if (_Cmp.second == _Last2) { - return 0; - } else { - return -1; + return 1; } - } - if (_Cmp.second == _Last2) { - return 1; - } - - if (_Traits::lt(*_Cmp.first, *_Cmp.second)) { - return -1; - } else { - return 1; + if (_Traits::lt(*_Cmp.first, *_Cmp.second)) { + return -1; + } else { + return 1; + } } } -template -int _Iter_compare2(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2) { - // decide which _Iter_compare implementation to use - return _Iter_compare3<_Traits>( - _First1, _Last1, _First2, _Last2, bool_constant, is_pointer<_FwdIt2>>>{}); -} - template int _Iter_compare(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2) { // compare two iterator ranges: From b3095c4ba5862b8d40e76e3f1fad910842c87bf8 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 27 Sep 2021 10:20:10 +0300 Subject: [PATCH 03/23] polymorphic_allocator --- stl/inc/xpolymorphic_allocator.h | 75 +++++++++++--------------------- 1 file changed, 25 insertions(+), 50 deletions(-) diff --git a/stl/inc/xpolymorphic_allocator.h b/stl/inc/xpolymorphic_allocator.h index 8ca32dc39f..7829a3d93e 100644 --- a/stl/inc/xpolymorphic_allocator.h +++ b/stl/inc/xpolymorphic_allocator.h @@ -23,64 +23,39 @@ _STL_DISABLE_CLANG_WARNINGS _STD_BEGIN #if !_HAS_CXX20 -template -void _Uses_allocator_construct2( - true_type, _Ty* const _Ptr, _Outer_alloc& _Outer, _Inner_alloc& _Inner, _Types&&... _Args) { - // uses-allocator construction of *_Ptr by alloc _Outer propagating alloc _Inner, allocator_arg_t case - allocator_traits<_Outer_alloc>::construct(_Outer, _Ptr, allocator_arg, _Inner, _STD forward<_Types>(_Args)...); -} - -template -void _Uses_allocator_construct2( - false_type, _Ty* const _Ptr, _Outer_alloc& _Outer, _Inner_alloc& _Inner, _Types&&... _Args) { - // uses-allocator construction of *_Ptr by alloc _Outer propagating alloc _Inner, non-allocator_arg_t case - static_assert(is_constructible_v<_Ty, _Types..., _Inner_alloc&>, - "N4700 23.10.7.2 [allocator.uses.construction]/1 requires " - "is_constructible_v when uses_allocator_v is true and " - "is_constructible_v is false"); - allocator_traits<_Outer_alloc>::construct(_Outer, _Ptr, _STD forward<_Types>(_Args)..., _Inner); -} - -template -void _Uses_allocator_construct1( - true_type, _Ty* const _Ptr, _Outer_alloc& _Outer, _Inner_alloc& _Inner, _Types&&... _Args) { - // uses-allocator construction of *_Ptr by alloc _Outer propagating alloc _Inner, - // uses_allocator_v<_Ty, _Inner_alloc> case - using _IsConstructible = typename is_constructible<_Ty, allocator_arg_t, _Inner_alloc&, _Types...>::type; - _Uses_allocator_construct2(_IsConstructible{}, _Ptr, _Outer, _Inner, _STD forward<_Types>(_Args)...); -} - -template -void _Uses_allocator_construct1(false_type, _Ty* const _Ptr, _Outer_alloc& _Outer, _Inner_alloc&, _Types&&... _Args) { - // uses-allocator construction of *_Ptr by alloc _Outer, !uses_allocator_v<_Ty, _Inner_alloc> case - static_assert(is_constructible_v<_Ty, _Types...>, - "N4700 23.10.7.2 [allocator.uses.construction]/1 requires " - "is_constructible_v when uses_allocator_v is false"); - allocator_traits<_Outer_alloc>::construct(_Outer, _Ptr, _STD forward<_Types>(_Args)...); -} - template , int> = 0> void _Uses_allocator_construct(_Ty* const _Ptr, _Outer_alloc& _Outer, _Inner_alloc& _Inner, _Types&&... _Args) { // uses-allocator construction of *_Ptr by alloc _Outer propagating alloc _Inner, non-pair case - _Uses_allocator_construct1(uses_allocator<_Ty, _Inner_alloc>{}, _Ptr, _Outer, _Inner, - _STD forward<_Types>(_Args)...); // TRANSITION, if constexpr -} - -template -auto _Uses_allocator_piecewise2(true_type, _Alloc& _Al, tuple<_Types...>&& _Tuple) { - return _STD tuple_cat(tuple(allocator_arg, _Al), _STD move(_Tuple)); -} - -template -auto _Uses_allocator_piecewise2(false_type, _Alloc& _Al, tuple<_Types...>&& _Tuple) { - return _STD tuple_cat(_STD move(_Tuple), tuple<_Alloc&>(_Al)); + if constexpr (uses_allocator<_Ty, _Inner_alloc>::value) { + if constexpr (is_constructible<_Ty, allocator_arg_t, _Inner_alloc&, _Types...>::value) { + // uses-allocator construction of *_Ptr by alloc _Outer propagating alloc _Inner, allocator_arg_t case + allocator_traits<_Outer_alloc>::construct( + _Outer, _Ptr, allocator_arg, _Inner, _STD forward<_Types>(_Args)...); + } else { + // uses-allocator construction of *_Ptr by alloc _Outer propagating alloc _Inner, non-allocator_arg_t case + static_assert(is_constructible_v<_Ty, _Types..., _Inner_alloc&>, + "N4700 23.10.7.2 [allocator.uses.construction]/1 requires " + "is_constructible_v when uses_allocator_v is true and " + "is_constructible_v is false"); + allocator_traits<_Outer_alloc>::construct(_Outer, _Ptr, _STD forward<_Types>(_Args)..., _Inner); + } + } else { + // uses-allocator construction of *_Ptr by alloc _Outer, !uses_allocator_v<_Ty, _Inner_alloc> case + static_assert(is_constructible_v<_Ty, _Types...>, + "N4700 23.10.7.2 [allocator.uses.construction]/1 requires " + "is_constructible_v when uses_allocator_v is false"); + allocator_traits<_Outer_alloc>::construct(_Outer, _Ptr, _STD forward<_Types>(_Args)...); + } } template auto _Uses_allocator_piecewise(true_type, _Alloc& _Al, tuple<_Types...>&& _Tuple) { - return _Uses_allocator_piecewise2( - is_constructible<_Ty, allocator_arg_t, _Alloc&, _Types...>(), _Al, _STD move(_Tuple)); + if constexpr (is_constructible<_Ty, allocator_arg_t, _Alloc&, _Types...>::value) { + return _STD tuple_cat(tuple(allocator_arg, _Al), _STD move(_Tuple)); + } else { + return _STD tuple_cat(_STD move(_Tuple), tuple<_Alloc&>(_Al)); + } } template From 56ff1badd56fc86ccbc7f6434d547d6bbec77f7a Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 27 Sep 2021 10:56:52 +0300 Subject: [PATCH 04/23] can use `_v` in polymorphic allocator --- stl/inc/xpolymorphic_allocator.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/xpolymorphic_allocator.h b/stl/inc/xpolymorphic_allocator.h index 7829a3d93e..f40960ce74 100644 --- a/stl/inc/xpolymorphic_allocator.h +++ b/stl/inc/xpolymorphic_allocator.h @@ -27,8 +27,8 @@ template , int> = 0> void _Uses_allocator_construct(_Ty* const _Ptr, _Outer_alloc& _Outer, _Inner_alloc& _Inner, _Types&&... _Args) { // uses-allocator construction of *_Ptr by alloc _Outer propagating alloc _Inner, non-pair case - if constexpr (uses_allocator<_Ty, _Inner_alloc>::value) { - if constexpr (is_constructible<_Ty, allocator_arg_t, _Inner_alloc&, _Types...>::value) { + if constexpr (uses_allocator_v<_Ty, _Inner_alloc>) { + if constexpr (is_constructible_v<_Ty, allocator_arg_t, _Inner_alloc&, _Types...>) { // uses-allocator construction of *_Ptr by alloc _Outer propagating alloc _Inner, allocator_arg_t case allocator_traits<_Outer_alloc>::construct( _Outer, _Ptr, allocator_arg, _Inner, _STD forward<_Types>(_Args)...); From 8169883e2f31154b0f3b75201a37b5464dc35a6d Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 27 Sep 2021 11:57:46 +0300 Subject: [PATCH 05/23] untag _Uses_allocator_piecewise more --- stl/inc/xpolymorphic_allocator.h | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/stl/inc/xpolymorphic_allocator.h b/stl/inc/xpolymorphic_allocator.h index f40960ce74..a11d463990 100644 --- a/stl/inc/xpolymorphic_allocator.h +++ b/stl/inc/xpolymorphic_allocator.h @@ -50,26 +50,25 @@ void _Uses_allocator_construct(_Ty* const _Ptr, _Outer_alloc& _Outer, _Inner_all } template -auto _Uses_allocator_piecewise(true_type, _Alloc& _Al, tuple<_Types...>&& _Tuple) { - if constexpr (is_constructible<_Ty, allocator_arg_t, _Alloc&, _Types...>::value) { - return _STD tuple_cat(tuple(allocator_arg, _Al), _STD move(_Tuple)); +tuple<_Types...>&& _Uses_allocator_piecewise(_Alloc&, tuple<_Types...>&& _Tuple) { + if constexpr (uses_allocator_v<_Ty, _Alloc>) { + if constexpr (is_constructible<_Ty, allocator_arg_t, _Alloc&, _Types...>::value) { + return _STD tuple_cat(tuple(allocator_arg, _Al), _STD move(_Tuple)); + } else { + return _STD tuple_cat(_STD move(_Tuple), tuple<_Alloc&>(_Al)); + } } else { - return _STD tuple_cat(_STD move(_Tuple), tuple<_Alloc&>(_Al)); + return _STD move(_Tuple); } } -template -tuple<_Types...>&& _Uses_allocator_piecewise(false_type, _Alloc&, tuple<_Types...>&& _Tuple) { - return _STD move(_Tuple); -} - template void _Uses_allocator_construct_pair(pair<_Ty1, _Ty2>* const _Ptr, _Outer_alloc& _Outer, _Inner_alloc& _Inner, tuple<_Types1...>&& _Val1, tuple<_Types2...>&& _Val2) { // uses-allocator construction of pair from _Val1 and _Val2 by alloc _Outer propagating alloc _Inner allocator_traits<_Outer_alloc>::construct(_Outer, _Ptr, piecewise_construct, - _Uses_allocator_piecewise<_Ty1>(uses_allocator<_Ty1, _Inner_alloc>{}, _Inner, _STD move(_Val1)), - _Uses_allocator_piecewise<_Ty2>(uses_allocator<_Ty2, _Inner_alloc>{}, _Inner, _STD move(_Val2))); + _Uses_allocator_piecewise<_Ty1>(_Inner, _STD move(_Val1)), + _Uses_allocator_piecewise<_Ty2>(_Inner, _STD move(_Val2))); } template From 96dc2d46171235e4109ec1f9ec497d6a6bd57d20 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 27 Sep 2021 11:59:26 +0300 Subject: [PATCH 06/23] _Al --- stl/inc/xpolymorphic_allocator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/xpolymorphic_allocator.h b/stl/inc/xpolymorphic_allocator.h index a11d463990..e3802839b1 100644 --- a/stl/inc/xpolymorphic_allocator.h +++ b/stl/inc/xpolymorphic_allocator.h @@ -50,7 +50,7 @@ void _Uses_allocator_construct(_Ty* const _Ptr, _Outer_alloc& _Outer, _Inner_all } template -tuple<_Types...>&& _Uses_allocator_piecewise(_Alloc&, tuple<_Types...>&& _Tuple) { +tuple<_Types...>&& _Uses_allocator_piecewise(_Alloc& _Al, tuple<_Types...>&& _Tuple) { if constexpr (uses_allocator_v<_Ty, _Alloc>) { if constexpr (is_constructible<_Ty, allocator_arg_t, _Alloc&, _Types...>::value) { return _STD tuple_cat(tuple(allocator_arg, _Al), _STD move(_Tuple)); From 6d126383cd32a6e6c1629f9776c66b59cedf4907 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 27 Sep 2021 12:25:22 +0300 Subject: [PATCH 07/23] ret type --- stl/inc/xpolymorphic_allocator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/xpolymorphic_allocator.h b/stl/inc/xpolymorphic_allocator.h index e3802839b1..6cb339e016 100644 --- a/stl/inc/xpolymorphic_allocator.h +++ b/stl/inc/xpolymorphic_allocator.h @@ -50,7 +50,7 @@ void _Uses_allocator_construct(_Ty* const _Ptr, _Outer_alloc& _Outer, _Inner_all } template -tuple<_Types...>&& _Uses_allocator_piecewise(_Alloc& _Al, tuple<_Types...>&& _Tuple) { +decltype(auto) _Uses_allocator_piecewise(_Alloc& _Al, tuple<_Types...>&& _Tuple) { if constexpr (uses_allocator_v<_Ty, _Alloc>) { if constexpr (is_constructible<_Ty, allocator_arg_t, _Alloc&, _Types...>::value) { return _STD tuple_cat(tuple(allocator_arg, _Al), _STD move(_Tuple)); From 0ccc22601abc28089b394c29d055cf19003527bf Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 28 Sep 2021 14:56:59 +0300 Subject: [PATCH 08/23] Update stl/inc/regex Co-authored-by: Michael Schellenberger Costa --- stl/inc/regex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/regex b/stl/inc/regex index 0e163c9d0a..8d968f8137 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -509,7 +509,7 @@ int _Iter_compare2(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _La _First1, static_cast(_Last1 - _First1), _First2, static_cast(_Last2 - _First2)); } else { // _Iter_compare for general ranges - const pair<_FwdIt1, _FwdIt2> _Cmp = _STD mismatch(_First1, _Last1, _First2, _Last2, _Char_traits_eq<_Traits>{}); + const auto _Cmp = _STD mismatch(_First1, _Last1, _First2, _Last2, _Char_traits_eq<_Traits>{}); if (_Cmp.first == _Last1) { if (_Cmp.second == _Last2) { From d603670b045624a920faa5a4ba41be91f3dae1f0 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Wed, 20 Oct 2021 14:31:29 +0300 Subject: [PATCH 09/23] _Within_limits --- stl/inc/xutility | 83 +++++++++++++++++++----------------------------- 1 file changed, 33 insertions(+), 50 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index d988b4eced..033b77765a 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -5081,62 +5081,45 @@ _NODISCARD constexpr auto lexicographical_compare_three_way( } #endif // __cpp_lib_concepts -template -_NODISCARD constexpr bool _Within_limits(const _Ty& _Val, true_type, true_type, _Any_tag, false_type) { - // signed _Elem, signed _Ty - return SCHAR_MIN <= _Val && _Val <= SCHAR_MAX; -} - -template -_NODISCARD constexpr bool _Within_limits(const _Ty& _Val, true_type, false_type, true_type, false_type) { - // signed _Elem, unsigned _Ty, -1 == static_cast<_Ty>(-1) - return _Val <= SCHAR_MAX || static_cast<_Ty>(SCHAR_MIN) <= _Val; -} - -template -_NODISCARD constexpr bool _Within_limits(const _Ty& _Val, true_type, false_type, false_type, false_type) { - // signed _Elem, unsigned _Ty, -1 != static_cast<_Ty>(-1) - return _Val <= SCHAR_MAX; -} - -template -_NODISCARD constexpr bool _Within_limits(const _Ty& _Val, false_type, true_type, _Any_tag, false_type) { - // unsigned _Elem, signed _Ty - return 0 <= _Val && _Val <= UCHAR_MAX; -} - -template -_NODISCARD constexpr bool _Within_limits(const _Ty& _Val, false_type, false_type, _Any_tag, false_type) { - // unsigned _Elem, unsigned _Ty - return _Val <= UCHAR_MAX; -} - -template -_NODISCARD constexpr bool _Within_limits(const _Ty& _Val, _Any_tag, _Any_tag, _Any_tag, true_type) { - // bool _Elem - return _Val == true || _Val == false; -} - template _NODISCARD constexpr bool _Within_limits(const _InIt&, const _Ty& _Val) { // check whether _Val is within the limits of _Elem - using _Elem = _Iter_value_t<_InIt>; - return _Within_limits(_Val, bool_constant>{}, bool_constant>{}, - bool_constant<-1 == static_cast<_Ty>(-1)>{}, bool_constant>{}); -} - -template -_NODISCARD constexpr bool _Within_limits(const _InIt&, const bool&) { // bools are always within the limits of _Elem - return true; -} - + if constexpr (is_same_v<_Ty, bool>) { + return true; + } #ifdef __cpp_lib_byte -template -_NODISCARD constexpr bool _Within_limits(const _InIt&, const byte&) { // bytes are only comparable with other bytes - return true; -} + if constexpr (is_same_v<_Ty, byte>) { + return true; + } #endif // __cpp_lib_byte + using _Elem = _Iter_value_t<_InIt>; + if constexpr (is_same_v<_Elem, bool>) { + return _Val == true || _Val == false; + } else if constexpr (is_signed_v<_Elem>) { + if (is_signed_v<_Ty>) { + // signed _Elem, signed _Ty + return SCHAR_MIN <= _Val && _Val <= SCHAR_MAX; + } else { + if constexpr (-1 == static_cast<_Ty>(-1)) { + // signed _Elem, unsigned _Ty, -1 == static_cast<_Ty>(-1) + return _Val <= SCHAR_MAX || static_cast<_Ty>(SCHAR_MIN) <= _Val; + } else { + // signed _Elem, unsigned _Ty, -1 != static_cast<_Ty>(-1) + return _Val <= SCHAR_MAX; + } + } + } else { + if (is_signed_v<_Ty>) { + // unsigned _Elem, signed _Ty + return 0 <= _Val && _Val <= UCHAR_MAX; + } else { + // unsigned _Elem, unsigned _Ty + return _Val <= UCHAR_MAX; + } + } +} + template _INLINE_VAR constexpr bool _Memchr_in_find_is_safe = _Iterator_is_contiguous<_Iter>&& From fb25b4ac96011c94b1310d249dbd29d41f4082f4 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Wed, 20 Oct 2021 14:53:30 +0300 Subject: [PATCH 10/23] @miscco review --- stl/inc/xutility | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 033b77765a..6156dfebdf 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -5088,34 +5088,35 @@ _NODISCARD constexpr bool _Within_limits(const _InIt&, const _Ty& _Val) { return true; } #ifdef __cpp_lib_byte - if constexpr (is_same_v<_Ty, byte>) { + else if constexpr (is_same_v<_Ty, byte>) { return true; } #endif // __cpp_lib_byte - - using _Elem = _Iter_value_t<_InIt>; - if constexpr (is_same_v<_Elem, bool>) { - return _Val == true || _Val == false; - } else if constexpr (is_signed_v<_Elem>) { - if (is_signed_v<_Ty>) { - // signed _Elem, signed _Ty - return SCHAR_MIN <= _Val && _Val <= SCHAR_MAX; - } else { - if constexpr (-1 == static_cast<_Ty>(-1)) { - // signed _Elem, unsigned _Ty, -1 == static_cast<_Ty>(-1) - return _Val <= SCHAR_MAX || static_cast<_Ty>(SCHAR_MIN) <= _Val; + else { + using _Elem = _Iter_value_t<_InIt>; + if constexpr (is_same_v<_Elem, bool>) { + return _Val == true || _Val == false; + } else if constexpr (is_signed_v<_Elem>) { + if (is_signed_v<_Ty>) { + // signed _Elem, signed _Ty + return SCHAR_MIN <= _Val && _Val <= SCHAR_MAX; } else { - // signed _Elem, unsigned _Ty, -1 != static_cast<_Ty>(-1) - return _Val <= SCHAR_MAX; + if constexpr (-1 == static_cast<_Ty>(-1)) { + // signed _Elem, unsigned _Ty, -1 == static_cast<_Ty>(-1) + return _Val <= SCHAR_MAX || static_cast<_Ty>(SCHAR_MIN) <= _Val; + } else { + // signed _Elem, unsigned _Ty, -1 != static_cast<_Ty>(-1) + return _Val <= SCHAR_MAX; + } } - } - } else { - if (is_signed_v<_Ty>) { - // unsigned _Elem, signed _Ty - return 0 <= _Val && _Val <= UCHAR_MAX; } else { - // unsigned _Elem, unsigned _Ty - return _Val <= UCHAR_MAX; + if (is_signed_v<_Ty>) { + // unsigned _Elem, signed _Ty + return 0 <= _Val && _Val <= UCHAR_MAX; + } else { + // unsigned _Elem, unsigned _Ty + return _Val <= UCHAR_MAX; + } } } } From 4097134f2f8167a8a9adaa509c6a50745ca3d16f Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Wed, 20 Oct 2021 15:26:15 +0300 Subject: [PATCH 11/23] sample --- stl/inc/algorithm | 44 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 12077672aa..218f6b0a35 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -4705,31 +4705,6 @@ _SampleIt _Sample_selection_unchecked( return _Dest; } -template -_SampleIt _Sample1(_PopIt _First, _PopIt _Last, _SampleIt _Dest, _Diff _Count, _RngFn& _RngFunc, input_iterator_tag) { - // source is input: use reservoir sampling (unstable) - // pre: _Count > 0 - _Seek_wrapped( - _Dest, _Sample_reservoir_unchecked(_First, _Last, _Get_unwrapped_unverified(_Dest), _Count, _RngFunc)); - return _Dest; -} - -template -_SampleIt _Sample1(_PopIt _First, _PopIt _Last, _SampleIt _Dest, _Diff _Count, _RngFn& _RngFunc, forward_iterator_tag) { - // source is forward: use selection sampling (stable) - // pre: _Count > 0 - using _PopDiff = _Iter_diff_t<_PopIt>; - using _CT = common_type_t<_Diff, _PopDiff>; - const auto _Pop_size = _STD distance(_First, _Last); - if (static_cast<_CT>(_Count) > static_cast<_CT>(_Pop_size)) { - _Count = static_cast<_Diff>(_Pop_size); // narrowing OK because _Count is getting smaller - } - - _Seek_wrapped( - _Dest, _Sample_selection_unchecked(_First, _Pop_size, _Get_unwrapped_n(_Dest, _Count), _Count, _RngFunc)); - return _Dest; -} - template _SampleIt sample(_PopIt _First, _PopIt _Last, _SampleIt _Dest, _Diff _Count, _Urng&& _Func) { // randomly select _Count elements from [_First, _Last) into _Dest @@ -4739,7 +4714,24 @@ _SampleIt sample(_PopIt _First, _PopIt _Last, _SampleIt _Dest, _Diff _Count, _Adl_verify_range(_First, _Last); if (0 < _Count) { _Rng_from_urng<_Iter_diff_t<_PopIt>, remove_reference_t<_Urng>> _RngFunc(_Func); - _Dest = _Sample1(_Get_unwrapped(_First), _Get_unwrapped(_Last), _Dest, _Count, _RngFunc, _Iter_cat_t<_PopIt>{}); + if constexpr (_Is_random_iter_v<_PopIt>) { + // source is input: use reservoir sampling (unstable) + // pre: _Count > 0 + _Seek_wrapped( + _Dest, _Sample_reservoir_unchecked(_First, _Last, _Get_unwrapped_unverified(_Dest), _Count, _RngFunc)); + } else { + // source is forward: use selection sampling (stable) + // pre: _Count > 0 + using _PopDiff = _Iter_diff_t<_PopIt>; + using _CT = common_type_t<_Diff, _PopDiff>; + const auto _Pop_size = _STD distance(_First, _Last); + if (static_cast<_CT>(_Count) > static_cast<_CT>(_Pop_size)) { + _Count = static_cast<_Diff>(_Pop_size); // narrowing OK because _Count is getting smaller + } + + _Seek_wrapped(_Dest, + _Sample_selection_unchecked(_First, _Pop_size, _Get_unwrapped_n(_Dest, _Count), _Count, _RngFunc)); + } } return _Dest; From 3554787fd0a22489c712d0694dcbde575514d162 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Wed, 20 Oct 2021 15:35:58 +0300 Subject: [PATCH 12/23] sample fix --- stl/inc/algorithm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 218f6b0a35..0f92c7f098 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -4714,12 +4714,7 @@ _SampleIt sample(_PopIt _First, _PopIt _Last, _SampleIt _Dest, _Diff _Count, _Adl_verify_range(_First, _Last); if (0 < _Count) { _Rng_from_urng<_Iter_diff_t<_PopIt>, remove_reference_t<_Urng>> _RngFunc(_Func); - if constexpr (_Is_random_iter_v<_PopIt>) { - // source is input: use reservoir sampling (unstable) - // pre: _Count > 0 - _Seek_wrapped( - _Dest, _Sample_reservoir_unchecked(_First, _Last, _Get_unwrapped_unverified(_Dest), _Count, _RngFunc)); - } else { + if constexpr (_Is_fwd_iter_v<_PopIt>) { // source is forward: use selection sampling (stable) // pre: _Count > 0 using _PopDiff = _Iter_diff_t<_PopIt>; @@ -4731,6 +4726,11 @@ _SampleIt sample(_PopIt _First, _PopIt _Last, _SampleIt _Dest, _Diff _Count, _Seek_wrapped(_Dest, _Sample_selection_unchecked(_First, _Pop_size, _Get_unwrapped_n(_Dest, _Count), _Count, _RngFunc)); + } else { + // source is input: use reservoir sampling (unstable) + // pre: _Count > 0 + _Seek_wrapped( + _Dest, _Sample_reservoir_unchecked(_First, _Last, _Get_unwrapped_unverified(_Dest), _Count, _RngFunc)); } } From c2b73bcfb47d38218b63f32be7a0c6ad6ee670f2 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Wed, 20 Oct 2021 15:37:06 +0300 Subject: [PATCH 13/23] Pre is checked --- stl/inc/algorithm | 2 -- 1 file changed, 2 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 0f92c7f098..98d08588cb 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -4716,7 +4716,6 @@ _SampleIt sample(_PopIt _First, _PopIt _Last, _SampleIt _Dest, _Diff _Count, _Rng_from_urng<_Iter_diff_t<_PopIt>, remove_reference_t<_Urng>> _RngFunc(_Func); if constexpr (_Is_fwd_iter_v<_PopIt>) { // source is forward: use selection sampling (stable) - // pre: _Count > 0 using _PopDiff = _Iter_diff_t<_PopIt>; using _CT = common_type_t<_Diff, _PopDiff>; const auto _Pop_size = _STD distance(_First, _Last); @@ -4728,7 +4727,6 @@ _SampleIt sample(_PopIt _First, _PopIt _Last, _SampleIt _Dest, _Diff _Count, _Sample_selection_unchecked(_First, _Pop_size, _Get_unwrapped_n(_Dest, _Count), _Count, _RngFunc)); } else { // source is input: use reservoir sampling (unstable) - // pre: _Count > 0 _Seek_wrapped( _Dest, _Sample_reservoir_unchecked(_First, _Last, _Get_unwrapped_unverified(_Dest), _Count, _RngFunc)); } From 00ead289e3bf4cbc7cfaa0d99a4114f5782f4f57 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Wed, 20 Oct 2021 15:40:42 +0300 Subject: [PATCH 14/23] constexpr --- stl/inc/xutility | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 6156dfebdf..740df98f96 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -5110,7 +5110,7 @@ _NODISCARD constexpr bool _Within_limits(const _InIt&, const _Ty& _Val) { } } } else { - if (is_signed_v<_Ty>) { + if constexpr (is_signed_v<_Ty>) { // unsigned _Elem, signed _Ty return 0 <= _Val && _Val <= UCHAR_MAX; } else { From 104a592c3a10c47757752915bcb642a556ff48ab Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Thu, 28 Oct 2021 19:49:37 +0300 Subject: [PATCH 15/23] is_permutation --- stl/inc/algorithm | 91 ++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 98d08588cb..ce3f73a2dd 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -824,66 +824,59 @@ _NODISCARD _CONSTEXPR20 bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _Fw } template -_CONSTEXPR20 bool _Is_permutation_unchecked(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred, - forward_iterator_tag, forward_iterator_tag) { - // test if [_First1, _Last1) == permuted [_First2, _Last2), arbitrary iterators - for (;; ++_First1, (void) ++_First2) { // trim matching prefix - if (_First1 == _Last1) { - return _First2 == _Last2; - } - - if (_First2 == _Last2) { +_NODISCARD _CONSTEXPR20 bool is_permutation( + _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred) { + // test if [_First1, _Last1) == permuted [_First2, _Last2) + _Adl_verify_range(_First1, _Last1); + _Adl_verify_range(_First2, _Last2); + if constexpr (_Is_random_iter_v<_FwdIt1> && _Is_random_iter_v<_FwdIt2>) { + // test if [_First1, _Last1) == permuted [_First2, _Last2), random-access iterators + if (_Last1 - _First1 != _Last2 - _First2) { return false; } - if (!_Pred(*_First1, *_First2)) { // found first inequality, check match counts in suffix - break; + for (; _First1 != _Last1; ++_First1, (void) ++_First2) { // trim matching prefix + if (!_Pred(*_First1, *_First2)) { + // found first inequality, check match counts in suffix + return _Check_match_counts(_First1, _Last1, _First2, _Last2, _Pred); + } } - } - auto _Next1 = _First1; - auto _Next2 = _First2; - for (;; ++_Next1, (void) ++_Next2) { // check for same lengths - if (_Next1 == _Last1) { - if (_Next2 == _Last2) { - return _Check_match_counts(_First1, _Last1, _First2, _Last2, _Pred); + return true; + } else if constexpr (_Is_fwd_iter_v<_FwdIt1> && _Is_fwd_iter_v<_FwdIt2>) { + // test if [_First1, _Last1) == permuted [_First2, _Last2), arbitrary iterators + for (;; ++_First1, (void) ++_First2) { // trim matching prefix + if (_First1 == _Last1) { + return _First2 == _Last2; } - return false; // sequence 1 is shorter than sequence 2, not a permutation - } + if (_First2 == _Last2) { + return false; + } - if (_Next2 == _Last2) { - return false; // sequence 1 is longer than sequence 2, not a permutation + if (!_Pred(*_First1, *_First2)) { // found first inequality, check match counts in suffix + break; + } } - } -} -template -_CONSTEXPR20 bool _Is_permutation_unchecked(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred, - random_access_iterator_tag, random_access_iterator_tag) { - // test if [_First1, _Last1) == permuted [_First2, _Last2), random-access iterators - if (_Last1 - _First1 != _Last2 - _First2) { - return false; - } + auto _Next1 = _First1; + auto _Next2 = _First2; + for (;; ++_Next1, (void) ++_Next2) { // check for same lengths + if (_Next1 == _Last1) { + if (_Next2 == _Last2) { + return _Check_match_counts(_First1, _Last1, _First2, _Last2, _Pred); + } - for (; _First1 != _Last1; ++_First1, (void) ++_First2) { // trim matching prefix - if (!_Pred(*_First1, *_First2)) { - // found first inequality, check match counts in suffix - return _Check_match_counts(_First1, _Last1, _First2, _Last2, _Pred); + return false; // sequence 1 is shorter than sequence 2, not a permutation + } + + if (_Next2 == _Last2) { + return false; // sequence 1 is longer than sequence 2, not a permutation + } } + } else { + static_assert(_Always_false<_FwdIt1>, "Iterators should be at least forward iterators"); } - - return true; -} - -template -_NODISCARD _CONSTEXPR20 bool is_permutation( - _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred) { - // test if [_First1, _Last1) == permuted [_First2, _Last2) - _Adl_verify_range(_First1, _Last1); - _Adl_verify_range(_First2, _Last2); - return _Is_permutation_unchecked(_Get_unwrapped(_First1), _Get_unwrapped(_Last1), _Get_unwrapped(_First2), - _Get_unwrapped(_Last2), _Pass_fn(_Pred), _Iter_cat_t<_FwdIt1>{}, _Iter_cat_t<_FwdIt2>{}); } template @@ -4725,10 +4718,12 @@ _SampleIt sample(_PopIt _First, _PopIt _Last, _SampleIt _Dest, _Diff _Count, _Seek_wrapped(_Dest, _Sample_selection_unchecked(_First, _Pop_size, _Get_unwrapped_n(_Dest, _Count), _Count, _RngFunc)); - } else { + } else if constexpr (_Is_input_iter_v<_PopIt>) { // source is input: use reservoir sampling (unstable) _Seek_wrapped( _Dest, _Sample_reservoir_unchecked(_First, _Last, _Get_unwrapped_unverified(_Dest), _Count, _RngFunc)); + } else { + static_assert(_Always_false<_PopIt>, "Source iterators must be at least input iterators"); } } From 7c83374a9e55a1e48cd0834cf851ea91c82a2bb2 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Thu, 28 Oct 2021 20:50:14 +0300 Subject: [PATCH 16/23] wrap everything --- stl/inc/algorithm | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index ce3f73a2dd..f27c8b70bf 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -826,54 +826,60 @@ _NODISCARD _CONSTEXPR20 bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _Fw template _NODISCARD _CONSTEXPR20 bool is_permutation( _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred) { - // test if [_First1, _Last1) == permuted [_First2, _Last2) + // test if [_UFirst1, _ULast1) == permuted [_UFirst2, _ULast2) _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); + auto _UFirst1 = _Get_unwrapped(_First1); + auto _UFirst2 = _Get_unwrapped(_First2); + auto _ULast1 = _Get_unwrapped(_Last1); + auto _ULast2 = _Get_unwrapped(_Last2); if constexpr (_Is_random_iter_v<_FwdIt1> && _Is_random_iter_v<_FwdIt2>) { - // test if [_First1, _Last1) == permuted [_First2, _Last2), random-access iterators - if (_Last1 - _First1 != _Last2 - _First2) { + // test if [_UFirst1, _ULast1) == permuted [_UFirst2, _ULast2), random-access iterators + if (_ULast1 - _UFirst1 != _ULast2 - _UFirst2) { return false; } - for (; _First1 != _Last1; ++_First1, (void) ++_First2) { // trim matching prefix - if (!_Pred(*_First1, *_First2)) { + for (; _UFirst1 != _ULast1; ++_UFirst1, (void) ++_UFirst2) { // trim matching prefix + if (!_Pred(*_UFirst1, *_UFirst2)) { // found first inequality, check match counts in suffix - return _Check_match_counts(_First1, _Last1, _First2, _Last2, _Pred); + return _Check_match_counts(_UFirst1, _ULast1, _UFirst2, _ULast2, _Pass_fn(_Pred)); } } return true; } else if constexpr (_Is_fwd_iter_v<_FwdIt1> && _Is_fwd_iter_v<_FwdIt2>) { - // test if [_First1, _Last1) == permuted [_First2, _Last2), arbitrary iterators - for (;; ++_First1, (void) ++_First2) { // trim matching prefix - if (_First1 == _Last1) { - return _First2 == _Last2; + // test if [_UFirst1, _ULast1) == permuted [_UFirst2, _ULast2), arbitrary iterators + for (;; ++_UFirst1, (void) ++_UFirst2) { // trim matching prefix + if (_UFirst1 == _ULast1) { + return _UFirst2 == _ULast2; } - if (_First2 == _Last2) { + if (_UFirst2 == _ULast2) { return false; } - if (!_Pred(*_First1, *_First2)) { // found first inequality, check match counts in suffix + if (!_Pred(*_UFirst1, *_UFirst2)) { // found first inequality, check match counts in suffix break; } } - auto _Next1 = _First1; - auto _Next2 = _First2; + auto _Next1 = _UFirst1; + auto _Next2 = _UFirst2; for (;; ++_Next1, (void) ++_Next2) { // check for same lengths - if (_Next1 == _Last1) { - if (_Next2 == _Last2) { - return _Check_match_counts(_First1, _Last1, _First2, _Last2, _Pred); + if (_Next1 == _ULast1) { + if (_Next2 == _ULast2) { + return _Check_match_counts(_UFirst1, _ULast1, _UFirst2, _ULast2, _Pass_fn(_Pred)); } return false; // sequence 1 is shorter than sequence 2, not a permutation } - if (_Next2 == _Last2) { + if (_Next2 == _ULast2) { return false; // sequence 1 is longer than sequence 2, not a permutation } } + + return true; } else { static_assert(_Always_false<_FwdIt1>, "Iterators should be at least forward iterators"); } From fdfa552bb7e33e4d37372365ad886387b4b9d2ed Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Thu, 28 Oct 2021 21:27:09 +0300 Subject: [PATCH 17/23] clang format --- stl/inc/algorithm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index f27c8b70bf..740f358a16 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -831,8 +831,8 @@ _NODISCARD _CONSTEXPR20 bool is_permutation( _Adl_verify_range(_First2, _Last2); auto _UFirst1 = _Get_unwrapped(_First1); auto _UFirst2 = _Get_unwrapped(_First2); - auto _ULast1 = _Get_unwrapped(_Last1); - auto _ULast2 = _Get_unwrapped(_Last2); + auto _ULast1 = _Get_unwrapped(_Last1); + auto _ULast2 = _Get_unwrapped(_Last2); if constexpr (_Is_random_iter_v<_FwdIt1> && _Is_random_iter_v<_FwdIt2>) { // test if [_UFirst1, _ULast1) == permuted [_UFirst2, _ULast2), random-access iterators if (_ULast1 - _UFirst1 != _ULast2 - _UFirst2) { From a62398de4adda945f119ac0feb402c4ed5dcfaed Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 5 Dec 2021 18:35:52 +0200 Subject: [PATCH 18/23] _Find_unchecked --- stl/inc/xutility | 66 +++++++++++++++++++----------------------------- 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 740df98f96..17b4b21df4 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -5121,19 +5121,35 @@ _NODISCARD constexpr bool _Within_limits(const _InIt&, const _Ty& _Val) { } } -template -_INLINE_VAR constexpr bool _Memchr_in_find_is_safe = - _Iterator_is_contiguous<_Iter>&& - disjunction_v, _Is_character_or_bool<_Iter_value_t<_Iter>>> +template +_NODISCARD _CONSTEXPR20 _InIt _Find_unchecked(_InIt _First, const _InIt _Last, const _Ty& _Val) { + // find first matching _Val; choose optimization + // activate optimization for contiguous iterators to (const) bytes and integral values + // find first byte matching integral _Val +#if _HAS_CXX20 + if (!_STD is_constant_evaluated()) +#endif // _HAS_CXX20 + { + if constexpr (_Iterator_is_contiguous<_InIt> && + disjunction_v, _Is_character_or_bool<_Iter_value_t<_InIt>>> #ifdef __cpp_lib_byte - , - conjunction, is_same<_Iter_value_t<_Iter>, byte>> + , conjunction, is_same<_Iter_value_t<_InIt>, byte>> #endif // __cpp_lib_byte - > && !is_volatile_v>>; + > && !is_volatile_v>>) { + if (!_Within_limits(_First, _Val)) { + return _Last; + } + const auto _First_ptr = _To_address(_First); + const auto _Result = static_cast>*>( + _CSTD memchr(_First_ptr, static_cast(_Val), static_cast(_Last - _First))); + if constexpr (is_pointer_v<_InIt>) { + return _Result ? _Result : _Last; + } else { + return _Result ? _First + (_Result - _First_ptr) : _Last; + } + } + } -template -_NODISCARD constexpr _InIt _Find_unchecked1(_InIt _First, const _InIt _Last, const _Ty& _Val, false_type) { - // find first matching _Val for (; _First != _Last; ++_First) { if (*_First == _Val) { break; @@ -5143,36 +5159,6 @@ _NODISCARD constexpr _InIt _Find_unchecked1(_InIt _First, const _InIt _Last, con return _First; } -template -_NODISCARD _CONSTEXPR20 _InIt _Find_unchecked1(_InIt _First, const _InIt _Last, const _Ty& _Val, true_type) { - // find first byte matching integral _Val - if (!_Within_limits(_First, _Val)) { - return _Last; - } - -#if _HAS_CXX20 - if (_STD is_constant_evaluated()) { - using _Elem = _Iter_value_t<_InIt>; - return _Find_unchecked1(_First, _Last, static_cast<_Elem>(_Val), false_type{}); - } -#endif // _HAS_CXX20 - const auto _First_ptr = _To_address(_First); - const auto _Result = static_cast>*>( - _CSTD memchr(_First_ptr, static_cast(_Val), static_cast(_Last - _First))); - if constexpr (is_pointer_v<_InIt>) { - return _Result ? _Result : _Last; - } else { - return _Result ? _First + (_Result - _First_ptr) : _Last; - } -} - -template -_NODISCARD _CONSTEXPR20 _InIt _Find_unchecked(const _InIt _First, const _InIt _Last, const _Ty& _Val) { - // find first matching _Val; choose optimization - // activate optimization for contiguous iterators to (const) bytes and integral values - return _Find_unchecked1(_First, _Last, _Val, bool_constant<_Memchr_in_find_is_safe<_InIt, _Ty>>{}); -} - template _NODISCARD _CONSTEXPR20 _InIt find(_InIt _First, const _InIt _Last, const _Ty& _Val) { // find first matching _Val _Adl_verify_range(_First, _Last); From b6118b0515f5abf15cdbb2b3934a4457c2e8d8fe Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 5 Dec 2021 18:57:39 +0200 Subject: [PATCH 19/23] restore _Memchr_in_find_is_safe --- stl/inc/xutility | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 17b4b21df4..2952a8c155 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -5121,6 +5121,16 @@ _NODISCARD constexpr bool _Within_limits(const _InIt&, const _Ty& _Val) { } } +template +_INLINE_VAR constexpr bool _Memchr_in_find_is_safe = + _Iterator_is_contiguous<_Iter>&& + disjunction_v, _Is_character_or_bool<_Iter_value_t<_Iter>>> +#ifdef __cpp_lib_byte + , + conjunction, is_same<_Iter_value_t<_Iter>, byte>> +#endif // __cpp_lib_byte + > && !is_volatile_v>>; + template _NODISCARD _CONSTEXPR20 _InIt _Find_unchecked(_InIt _First, const _InIt _Last, const _Ty& _Val) { // find first matching _Val; choose optimization @@ -5130,12 +5140,7 @@ _NODISCARD _CONSTEXPR20 _InIt _Find_unchecked(_InIt _First, const _InIt _Last, c if (!_STD is_constant_evaluated()) #endif // _HAS_CXX20 { - if constexpr (_Iterator_is_contiguous<_InIt> && - disjunction_v, _Is_character_or_bool<_Iter_value_t<_InIt>>> -#ifdef __cpp_lib_byte - , conjunction, is_same<_Iter_value_t<_InIt>, byte>> -#endif // __cpp_lib_byte - > && !is_volatile_v>>) { + if constexpr (_Memchr_in_find_is_safe<_InIt>) { if (!_Within_limits(_First, _Val)) { return _Last; } From 9a9cc4bee05668c159b6bae2ef16d3ce37c09e0c Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 5 Dec 2021 18:59:21 +0200 Subject: [PATCH 20/23] restore _Memchr_in_find_is_safe missing param --- stl/inc/xutility | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 2952a8c155..21abfc7de7 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -5140,7 +5140,7 @@ _NODISCARD _CONSTEXPR20 _InIt _Find_unchecked(_InIt _First, const _InIt _Last, c if (!_STD is_constant_evaluated()) #endif // _HAS_CXX20 { - if constexpr (_Memchr_in_find_is_safe<_InIt>) { + if constexpr (_Memchr_in_find_is_safe<_InIt, _Ty>) { if (!_Within_limits(_First, _Val)) { return _Last; } From 606f69fbef72e99b12628ff64834909039fb006c Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 9 Dec 2021 17:25:03 -0800 Subject: [PATCH 21/23] Move comment. --- stl/inc/xutility | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 7fe39627c3..1351b542d3 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -5135,12 +5135,12 @@ template _NODISCARD _CONSTEXPR20 _InIt _Find_unchecked(_InIt _First, const _InIt _Last, const _Ty& _Val) { // find first matching _Val; choose optimization // activate optimization for contiguous iterators to (const) bytes and integral values - // find first byte matching integral _Val #if _HAS_CXX20 if (!_STD is_constant_evaluated()) #endif // _HAS_CXX20 { if constexpr (_Memchr_in_find_is_safe<_InIt, _Ty>) { + // find first byte matching integral _Val if (!_Within_limits(_First, _Val)) { return _Last; } From ef3196c9c869a76371995eaf174637769493271f Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 10 Dec 2021 10:06:06 +0200 Subject: [PATCH 22/23] Update stl/inc/xutility Co-authored-by: S. B. Tam --- stl/inc/xutility | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 1351b542d3..049ce8320a 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -5097,7 +5097,7 @@ _NODISCARD constexpr bool _Within_limits(const _InIt&, const _Ty& _Val) { if constexpr (is_same_v<_Elem, bool>) { return _Val == true || _Val == false; } else if constexpr (is_signed_v<_Elem>) { - if (is_signed_v<_Ty>) { + if constexpr (is_signed_v<_Ty>) { // signed _Elem, signed _Ty return SCHAR_MIN <= _Val && _Val <= SCHAR_MAX; } else { From 1e6fd4cb5e4eacdf6af8fa7ebc4f73dc7012a126 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Fri, 17 Dec 2021 18:21:38 -0800 Subject: [PATCH 23/23] Document `_Within_limits` precondition right on the tin --- stl/inc/xutility | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/inc/xutility b/stl/inc/xutility index 03e4dd0280..0d22298ef5 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -5100,6 +5100,7 @@ _NODISCARD constexpr bool _Within_limits(const _InIt&, const _Ty& _Val) { #endif // __cpp_lib_byte else { using _Elem = _Iter_value_t<_InIt>; + _STL_INTERNAL_STATIC_ASSERT(sizeof(_Elem) == 1); if constexpr (is_same_v<_Elem, bool>) { return _Val == true || _Val == false; } else if constexpr (is_signed_v<_Elem>) {