diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 06eedde67d8..0a0d3aa640f 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -17,14 +17,6 @@ _STL_DISABLE_CLANG_WARNINGS #pragma push_macro("new") #undef new -#if (defined(_M_IX86) || defined(_M_X64)) && !defined(_M_CEE_PURE) && !defined(_M_HYBRID) -_EXTERN_C -// See note about "noalias" in -__declspec(noalias) void __cdecl __std_swap_ranges_trivially_swappable_noalias( - void* _First1, void* _Last1, void* _First2) noexcept; -_END_EXTERN_C -#endif // (defined(_M_IX86) || defined(_M_X64)) && !defined(_M_CEE_PURE) && !defined(_M_HYBRID) - _STD_BEGIN // COMMON SORT PARAMETERS _INLINE_VAR constexpr int _ISORT_MAX = 32; // maximum size for insertion sort @@ -34,13 +26,13 @@ template constexpr ptrdiff_t _Temporary_buffer_size(const _Diff _Value) noexcept { // convert an iterator difference_type to a ptrdiff_t for use in temporary buffers using _CT = common_type_t; - return static_cast(_Min_value(static_cast<_CT>(PTRDIFF_MAX), static_cast<_CT>(_Value))); + return static_cast((_STD min)(static_cast<_CT>(PTRDIFF_MAX), static_cast<_CT>(_Value))); } template struct _Optimistic_temporary_buffer { // temporary storage with _alloca-like attempt static constexpr size_t _Optimistic_size = 4096; // default to ~1 page - static constexpr size_t _Optimistic_count = _Max_value(static_cast(1), _Optimistic_size / sizeof(_Ty)); + static constexpr size_t _Optimistic_count = (_STD max)(static_cast(1), _Optimistic_size / sizeof(_Ty)); template explicit _Optimistic_temporary_buffer(const _Diff _Requested_size) noexcept { // get temporary storage @@ -323,7 +315,7 @@ _NODISCARD _CONSTEXPR20 pair<_InIt1, _InIt2> mismatch( using _CT = _Common_diff_t<_InIt1, _InIt2>; const _CT _Count1 = _ULast1 - _UFirst1; const _CT _Count2 = _ULast2 - _UFirst2; - const auto _Count = static_cast<_Iter_diff_t<_InIt1>>(_Min_value(_Count1, _Count2)); + const auto _Count = static_cast<_Iter_diff_t<_InIt1>>((_STD min)(_Count1, _Count2)); _ULast1 = _UFirst1 + _Count; while (_UFirst1 != _ULast1 && _Pred(*_UFirst1, *_UFirst2)) { ++_UFirst1; @@ -360,7 +352,7 @@ pair<_InIt1, _InIt2> _Mismatch_unchecked(const _InIt1 _First1, const _InIt1 _Las using _CT = _Common_diff_t<_InIt1, _InIt2>; const _CT _Count1 = _Last1 - _First1; const _CT _Count2 = _Last2 - _First2; - const auto _Count = static_cast<_Iter_diff_t<_InIt1>>(_Min_value(_Count1, _Count2)); + const auto _Count = static_cast<_Iter_diff_t<_InIt1>>((_STD min)(_Count1, _Count2)); return _STD mismatch(_First1, _First1 + _Count, _First2, _Pred); } @@ -1259,38 +1251,7 @@ _NODISCARD _FwdIt1 find_first_of(_ExPo&& _Exec, const _FwdIt1 _First1, const _Fw } #endif // _HAS_CXX17 - // FUNCTION TEMPLATE swap_ranges -template -_CONSTEXPR20 _FwdIt2 _Swap_ranges_unchecked(_FwdIt1 _First1, const _FwdIt1 _Last1, _FwdIt2 _First2) { - // swap [_First1, _Last1) with [_First2, ...), no special optimization - for (; _First1 != _Last1; ++_First1, (void) ++_First2) { - _STD iter_swap(_First1, _First2); - } - - return _First2; -} - -#if (defined(_M_IX86) || defined(_M_X64)) && !defined(_M_CEE_PURE) && !defined(_M_HYBRID) -template , int> = 0> -_CONSTEXPR20 _Ty* _Swap_ranges_unchecked(_Ty* _First1, _Ty* const _Last1, _Ty* _First2) { - // swap [_First1, _Last1) with [_First2, ...), trivially swappable optimization -#ifdef __cpp_lib_is_constant_evaluated - if (!_STD is_constant_evaluated()) -#endif // __cpp_lib_is_constant_evaluated - { - __std_swap_ranges_trivially_swappable_noalias(_First1, _Last1, _First2); - return _First2 + (_Last1 - _First1); - } - - for (; _First1 != _Last1; ++_First1, (void) ++_First2) { - _STD iter_swap(_First1, _First2); - } - - return _First2; -} -#endif // (defined(_M_IX86) || defined(_M_X64)) && !defined(_M_CEE_PURE) && !defined(_M_HYBRID) - template _CONSTEXPR20 _FwdIt2 swap_ranges(const _FwdIt1 _First1, const _FwdIt1 _Last1, _FwdIt2 _First2) { // swap [_First1, _Last1) with [_First2, ...) @@ -3363,7 +3324,7 @@ void inplace_merge(_BidIt _First, _BidIt _Mid, _BidIt _Last, _Pr _Pred) { } const _Diff _Count2 = _STD distance(_UMid, _ULast); - _Optimistic_temporary_buffer<_Iter_value_t<_BidIt>> _Temp_buf{_Min_value(_Count1, _Count2)}; + _Optimistic_temporary_buffer<_Iter_value_t<_BidIt>> _Temp_buf{(_STD min)(_Count1, _Count2)}; _Buffered_inplace_merge_unchecked_impl( _UFirst, _UMid, _ULast, _Count1, _Count2, _Temp_buf._Data, _Temp_buf._Capacity, _Pass_fn(_Pred)); } @@ -3633,7 +3594,7 @@ void _Uninitialized_chunked_merge_unchecked(_BidIt _First, const _BidIt _Last, _ while (_Chunk < _Count) { _Count -= _Chunk; const _BidIt _Mid1 = _STD next(_First, _Chunk); - const auto _Chunk2 = _Min_value(_Chunk, _Count); + const auto _Chunk2 = (_STD min)(_Chunk, _Count); _Count -= _Chunk2; const _BidIt _Mid2 = _STD next(_Mid1, _Chunk2); _Backout._Last = _Uninitialized_merge_move(_First, _Mid1, _Mid2, _Backout._Last, _Pred); @@ -3653,7 +3614,7 @@ void _Chunked_merge_unchecked(_BidIt _First, const _BidIt _Last, _OutIt _Dest, c while (_Chunk < _Count) { _Count -= _Chunk; const _BidIt _Mid1 = _STD next(_First, _Chunk); - const auto _Chunk2 = _Min_value(_Chunk, _Count); + const auto _Chunk2 = (_STD min)(_Chunk, _Count); _Count -= _Chunk2; const _BidIt _Mid2 = _STD next(_Mid1, _Chunk2); _Dest = _Merge_move(_First, _Mid1, _Mid2, _Dest, _Pred); @@ -4533,14 +4494,7 @@ _NODISCARD pair<_FwdIt, _FwdIt> minmax_element(_ExPo&&, _FwdIt _First, _FwdIt _L } #endif // _HAS_CXX17 -// FUNCTION TEMPLATE max -template -_NODISCARD constexpr const _Ty&(max)(const _Ty& _Left, const _Ty& _Right, _Pr _Pred) noexcept( - noexcept(_DEBUG_LT_PRED(_Pred, _Left, _Right))) /* strengthened */ { - // return larger of _Left and _Right using _Pred - return _DEBUG_LT_PRED(_Pred, _Left, _Right) ? _Right : _Left; -} - +// FUNCTION TEMPLATE max (for initializer_list) template _NODISCARD constexpr _Ty(max)(initializer_list<_Ty> _Ilist, _Pr _Pred) { // return leftmost/largest @@ -4548,35 +4502,13 @@ _NODISCARD constexpr _Ty(max)(initializer_list<_Ty> _Ilist, _Pr _Pred) { return *_Res; } -#pragma warning(push) -#pragma warning(disable : 28285) // (syntax error in SAL annotation, occurs when _Ty is not an integral type) -template -_NODISCARD _Post_equal_to_(_Left < _Right ? _Right : _Left) constexpr const _Ty&(max)( - const _Ty& _Left, const _Ty& _Right) noexcept(noexcept(_Left < _Right)) /* strengthened */ { - // return larger of _Left and _Right - if (_Left < _Right) { - _STL_ASSERT(!(_Right < _Left), "invalid comparator"); - return _Right; - } - - return _Left; -} -#pragma warning(pop) - template _NODISCARD constexpr _Ty(max)(initializer_list<_Ty> _Ilist) { // return leftmost/largest return (_STD max)(_Ilist, less<>()); } -// FUNCTION TEMPLATE min -template -_NODISCARD constexpr const _Ty&(min)(const _Ty& _Left, const _Ty& _Right, _Pr _Pred) noexcept( - noexcept(_DEBUG_LT_PRED(_Pred, _Right, _Left))) /* strengthened */ { - // return smaller of _Left and _Right using _Pred - return _DEBUG_LT_PRED(_Pred, _Right, _Left) ? _Right : _Left; -} - +// FUNCTION TEMPLATE min (for initializer_list) template _NODISCARD constexpr _Ty(min)(initializer_list<_Ty> _Ilist, _Pr _Pred) { // return leftmost/smallest @@ -4584,21 +4516,6 @@ _NODISCARD constexpr _Ty(min)(initializer_list<_Ty> _Ilist, _Pr _Pred) { return *_Res; } -#pragma warning(push) -#pragma warning(disable : 28285) // (syntax error in SAL annotation, occurs when _Ty is not an integral type) -template -_NODISCARD _Post_equal_to_(_Right < _Left ? _Right : _Left) constexpr const _Ty&(min)( - const _Ty& _Left, const _Ty& _Right) noexcept(noexcept(_Right < _Left)) /* strengthened */ { - // return smaller of _Left and _Right - if (_Right < _Left) { - _STL_ASSERT(!(_Left < _Right), "invalid comparator"); - return _Right; - } - - return _Left; -} -#pragma warning(pop) - template _NODISCARD constexpr _Ty(min)(initializer_list<_Ty> _Ilist) { // return leftmost/smallest diff --git a/stl/inc/array b/stl/inc/array index 2a21b121b21..f6ab07d9cdb 100644 --- a/stl/inc/array +++ b/stl/inc/array @@ -8,9 +8,7 @@ #define _ARRAY_ #include #if _STL_COMPILER_PREPROCESSOR -#include -#include -#include +#include #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) diff --git a/stl/inc/charconv b/stl/inc/charconv index 1bdf62569f4..1f2b0077a9d 100644 --- a/stl/inc/charconv +++ b/stl/inc/charconv @@ -827,7 +827,7 @@ _NODISCARD inline bool _Multiply_by_power_of_ten(_Big_integer_flt& _Xval, const for (uint32_t _Large_power = _Power / 10; _Large_power != 0;) { const uint32_t _Current_power = - _Min_value(_Large_power, static_cast(_STD size(_Large_power_indices))); + (_STD min)(_Large_power, static_cast(_STD size(_Large_power_indices))); const _Unpack_index& _Index = _Large_power_indices[_Current_power - 1]; _Big_integer_flt _Multiplier{}; @@ -1504,8 +1504,8 @@ _NODISCARD errc _Convert_decimal_string_to_floating_type( // fractional part. If the exponent is positive, then the integer part consists of the first 'exponent' digits, // or all present digits if there are fewer digits. If the exponent is zero or negative, then the integer part // is empty. In either case, the remaining digits form the fractional part of the mantissa. - const uint32_t _Positive_exponent = static_cast(_Max_value(0, _Data._Myexponent)); - const uint32_t _Integer_digits_present = _Min_value(_Positive_exponent, _Data._Mymantissa_count); + const uint32_t _Positive_exponent = static_cast((_STD max)(0, _Data._Myexponent)); + const uint32_t _Integer_digits_present = (_STD min)(_Positive_exponent, _Data._Mymantissa_count); const uint32_t _Integer_digits_missing = _Positive_exponent - _Integer_digits_present; const uint8_t* const _Integer_first = _Data._Mymantissa; const uint8_t* const _Integer_last = _Data._Mymantissa + _Integer_digits_present; @@ -1767,7 +1767,7 @@ _NODISCARD from_chars_result _Ordinary_floating_from_chars(const char* const _Fi // For "03333.111", it is 4. // For "00000.111", it is 0. // For "00000.001", it is -2. - int _Exponent_adjustment = static_cast(_Min_value(_Whole_end - _Leading_zero_end, _Maximum_adjustment)); + int _Exponent_adjustment = static_cast((_STD min)(_Whole_end - _Leading_zero_end, _Maximum_adjustment)); // [_Whole_end, _Dot_end) will contain 0 or 1 '.' characters if (_Next != _Last && *_Next == '.') { @@ -1783,7 +1783,7 @@ _NODISCARD from_chars_result _Ordinary_floating_from_chars(const char* const _Fi for (; _Next != _Last && *_Next == '0'; ++_Next) { } - _Exponent_adjustment = static_cast(_Max_value(_Dot_end - _Next, _Minimum_adjustment)); + _Exponent_adjustment = static_cast((_STD max)(_Dot_end - _Next, _Minimum_adjustment)); } // Scan the fractional part of the mantissa: @@ -2869,7 +2869,7 @@ _NODISCARD inline to_chars_result _Floating_to_chars_general_precision( _Table_end = _Table_begin + _Precision + 5; } else { _Table_begin = _Tables::_Ordinary_X_table; - _Table_end = _Table_begin + _Min_value(_Precision, _Tables::_Max_P) + 5; + _Table_end = _Table_begin + (_STD min)(_Precision, _Tables::_Max_P) + 5; } // Profiling indicates that linear search is faster than binary search for small tables. @@ -2916,13 +2916,13 @@ _NODISCARD inline to_chars_result _Floating_to_chars_general_precision( // Write into the local buffer. // Clamping _Effective_precision allows _Buffer to be as small as possible, and increases efficiency. if (_Use_fixed_notation) { - _Effective_precision = _Min_value(_Precision - (_Scientific_exponent_X + 1), _Max_fixed_precision); + _Effective_precision = (_STD min)(_Precision - (_Scientific_exponent_X + 1), _Max_fixed_precision); const to_chars_result _Buf_result = _Floating_to_chars_fixed_precision(_Buffer, _STD end(_Buffer), _Value, _Effective_precision); _STL_INTERNAL_CHECK(_Buf_result.ec == errc{}); _Significand_last = _Buf_result.ptr; } else { - _Effective_precision = _Min_value(_Precision - 1, _Max_scientific_precision); + _Effective_precision = (_STD min)(_Precision - 1, _Max_scientific_precision); const to_chars_result _Buf_result = _Floating_to_chars_scientific_precision(_Buffer, _STD end(_Buffer), _Value, _Effective_precision); _STL_INTERNAL_CHECK(_Buf_result.ec == errc{}); diff --git a/stl/inc/deque b/stl/inc/deque index 131c2442557..b7a0b4a5c7b 100644 --- a/stl/inc/deque +++ b/stl/inc/deque @@ -1002,7 +1002,7 @@ public: } _NODISCARD size_type max_size() const noexcept { - return _Min_value( + return (_STD min)( static_cast((numeric_limits::max)()), _Alty_traits::max_size(_Getal())); } @@ -1175,7 +1175,7 @@ public: _Orphan_all(); auto _Myfirst = _Unchecked_begin(); const auto _Oldsize = _Mysize(); - auto _Assign_count = _Min_value(_Count, _Oldsize); + auto _Assign_count = (_STD min)(_Count, _Oldsize); for (; 0 < _Assign_count; --_Assign_count) { *_Myfirst = _Val; ++_Myfirst; diff --git a/stl/inc/execution b/stl/inc/execution index ebfb717d802..7e16aa4280a 100644 --- a/stl/inc/execution +++ b/stl/inc/execution @@ -189,7 +189,7 @@ public: } void _Submit_for_chunks(const size_t _Hw_threads, const size_t _Chunks) const noexcept { - _Submit(_Min_value(_Hw_threads * _Oversubmission_multiplier, _Chunks)); + _Submit((_STD min)(_Hw_threads * _Oversubmission_multiplier, _Chunks)); } private: @@ -229,7 +229,7 @@ constexpr size_t _Get_chunked_work_chunk_count(const size_t _Hw_threads, const _ // get the number of chunks to break work into to parallelize const auto _Size_count = static_cast(_Count); // no overflow due to forward iterators // we assume _Hw_threads * _Oversubscription_multiplier does not overflow - return _Min_value(_Hw_threads * _Oversubscription_multiplier, _Size_count); + return (_STD min)(_Hw_threads * _Oversubscription_multiplier, _Size_count); } // FUNCTION TEMPLATE _Get_least2_chunked_work_chunk_count @@ -797,7 +797,7 @@ struct _Static_partition_team { // common data for all static partitioned ops _Diff _Get_chunk_offset(const size_t _This_chunk) const { const auto _This_chunk_diff = static_cast<_Diff>(_This_chunk); - return _This_chunk_diff * _Chunk_size + _Min_value(_This_chunk_diff, _Unchunked_items); + return _This_chunk_diff * _Chunk_size + (_STD min)(_This_chunk_diff, _Unchunked_items); } _Static_partition_key<_Diff> _Get_next_key() { @@ -1026,7 +1026,7 @@ _Common_diff_t<_InIt1, _InIt2> _Distance_min(_InIt1 _First1, const _InIt1 _Last1 if constexpr (_Is_random_iter_v<_InIt1> && _Is_random_iter_v<_InIt2>) { const _CT _Count1 = _Last1 - _First1; const _CT _Count2 = _Last2 - _First2; - _Result = _Min_value(_Count1, _Count2); + _Result = (_STD min)(_Count1, _Count2); } else if constexpr (_Is_random_iter_v<_InIt1>) { for (auto _Count1 = _Last1 - _First1; 0 < _Count1 && _First2 != _Last2; --_Count1) { ++_First2; @@ -2814,7 +2814,7 @@ struct _Static_partitioned_temporary_buffer2 { ptrdiff_t _Get_offset(const size_t _Chunk_number) { // get the offset of the first element of the temporary buffer allocated to chunk _Chunk_number auto _Diff_chunk = static_cast(_Chunk_number); - return _Diff_chunk * _Chunk_size + _Min_value(_Diff_chunk, _Unchunked_items); + return _Diff_chunk * _Chunk_size + (_STD min)(_Diff_chunk, _Unchunked_items); } void _Destroy_all() { // destroy each element of the temporary buffer @@ -2845,13 +2845,13 @@ inline size_t _Get_stable_sort_tree_height(const size_t _Count, const size_t _Hw #else // ^^^ _WIN64 ^^^ // vvv !_WIN64 vvv const size_t _Max_tree_height = 30; #endif // _WIN64 - const size_t _Clamped_ideal_chunks = _Min_value(_Max_tree_height, _Log_ideal_chunks); + const size_t _Clamped_ideal_chunks = (_STD min)(_Max_tree_height, _Log_ideal_chunks); // similarly, if _Clamped_ideal_chunks is odd, that would break our 2 to even power invariant, // so go to the next higher power of 2 const auto _Ideal_tree_height = _Clamped_ideal_chunks + (_Clamped_ideal_chunks & 0x1U); - return _Min_value(_Count_max_tree_height, _Ideal_tree_height); + return (_STD min)(_Count_max_tree_height, _Ideal_tree_height); } struct _Bottom_up_merge_tree { @@ -3302,7 +3302,7 @@ struct _Static_partitioned_is_heap_until { const auto _Chunk_offset = _Key._Start_at; const auto _Last = _Chunk_offset + _Chunk_range_size; - const auto _Initial = _Max_value(_Chunk_offset, _Diff{1}); + const auto _Initial = (_STD max)(_Chunk_offset, _Diff{1}); for (_Diff _Off = _Initial; _Off < _Last; ++_Off) { if (_DEBUG_LT_PRED(_Pred, *(_Range_first + ((_Off - 1) >> 1)), *(_Range_first + _Off))) { _Results._Imbue(_Key._Chunk_number, _Range_first + _Off); diff --git a/stl/inc/forward_list b/stl/inc/forward_list index 89ede1b0073..0458f4389dd 100644 --- a/stl/inc/forward_list +++ b/stl/inc/forward_list @@ -874,7 +874,7 @@ public: } _NODISCARD size_type max_size() const noexcept { - return _Min_value( + return (_STD min)( static_cast((numeric_limits::max)()), _Alnode_traits::max_size(_Getal())); } diff --git a/stl/inc/fstream b/stl/inc/fstream index f0fa407b396..fd055b38bc6 100644 --- a/stl/inc/fstream +++ b/stl/inc/fstream @@ -562,7 +562,7 @@ protected: const auto _Start_count = _Count; const auto _Available = static_cast(_Mysb::_Gnavail()); if (0 < _Available) { // copy from get area - const auto _Read_size = _Min_value(_Count_s, _Available); + const auto _Read_size = (_STD min)(_Count_s, _Available); _Traits::copy(_Ptr, _Mysb::gptr(), _Read_size); _Ptr += _Read_size; _Count_s -= _Read_size; diff --git a/stl/inc/functional b/stl/inc/functional index 14152accf31..ed211965708 100644 --- a/stl/inc/functional +++ b/stl/inc/functional @@ -1818,13 +1818,13 @@ void _Build_boyer_moore_delta_2_table(_Iter_diff_t<_RanItPat>* _Shifts, const _R for (_Diff _Idx = _Pat_size; _Idx > 0; --_Idx, (void) --_Suffix) { _Suffix_fn[static_cast(_Idx - 1)] = _Suffix; while (_Suffix < _Pat_size && !_Eq(_Pat_first[_Idx - 1], _Pat_first[_Suffix])) { - _Shifts[_Suffix] = _Min_value(_Shifts[_Suffix], _Pat_size - _Idx); + _Shifts[_Suffix] = (_STD min)(_Shifts[_Suffix], _Pat_size - _Idx); _Suffix = _Suffix_fn[static_cast(_Suffix)]; } } for (_Diff _Idx = 0; _Idx <= _Suffix; ++_Idx) { - _Shifts[_Idx] = _Min_value(_Shifts[_Idx], _Pat_size + _Suffix - _Idx); + _Shifts[_Idx] = (_STD min)(_Shifts[_Idx], _Pat_size + _Suffix - _Idx); } } @@ -1862,7 +1862,7 @@ pair<_RanItHaystack, _RanItHaystack> _Boyer_moore_search( --_Idx; --_UFirst; } while (_Eq(*_UFirst, _UPat_first[_Idx])); - _Shift = _Max_value(_Delta1._Lookup(*_UFirst), _Delta2[_Idx]); + _Shift = (_STD max)(_Delta1._Lookup(*_UFirst), _Delta2[_Idx]); } } diff --git a/stl/inc/iterator b/stl/inc/iterator index 5d722ac007f..dbcb87b5d97 100644 --- a/stl/inc/iterator +++ b/stl/inc/iterator @@ -19,6 +19,53 @@ _STL_DISABLE_CLANG_WARNINGS #undef new _STD_BEGIN +// CLASS TEMPLATE back_insert_iterator +template +class back_insert_iterator { // wrap pushes to back of container as output iterator +public: + using iterator_category = output_iterator_tag; + using value_type = void; + using difference_type = void; + using pointer = void; + using reference = void; + + using container_type = _Container; + + explicit back_insert_iterator(_Container& _Cont) noexcept /* strengthened */ : container(_STD addressof(_Cont)) {} + + back_insert_iterator& operator=(const typename _Container::value_type& _Val) { + container->push_back(_Val); + return *this; + } + + back_insert_iterator& operator=(typename _Container::value_type&& _Val) { + container->push_back(_STD move(_Val)); + return *this; + } + + _NODISCARD back_insert_iterator& operator*() noexcept /* strengthened */ { + return *this; + } + + back_insert_iterator& operator++() noexcept /* strengthened */ { + return *this; + } + + back_insert_iterator operator++(int) noexcept /* strengthened */ { + return *this; + } + +protected: + _Container* container; // pointer to container +}; + +// FUNCTION TEMPLATE back_inserter +template +_NODISCARD back_insert_iterator<_Container> back_inserter(_Container& _Cont) noexcept /* strengthened */ { + // return a back_insert_iterator + return back_insert_iterator<_Container>(_Cont); +} + // CLASS TEMPLATE front_insert_iterator template class front_insert_iterator { // wrap pushes to front of container as output iterator diff --git a/stl/inc/list b/stl/inc/list index 0d7b4dd742b..0bc2a0cdb2b 100644 --- a/stl/inc/list +++ b/stl/inc/list @@ -1193,7 +1193,7 @@ public: } _NODISCARD size_type max_size() const noexcept { - return _Min_value( + return (_STD min)( static_cast((numeric_limits::max)()), _Alnode_traits::max_size(_Getal())); } diff --git a/stl/inc/memory_resource b/stl/inc/memory_resource index 8efe9f6825c..fb24d858a43 100644 --- a/stl/inc/memory_resource +++ b/stl/inc/memory_resource @@ -333,7 +333,7 @@ namespace pmr { static constexpr bool _Prepare_oversized(size_t& _Bytes, size_t& _Align) noexcept { // adjust size and alignment to allow for an _Oversized_header - _Align = _Max_value(_Align, alignof(_Oversized_header)); + _Align = (_STD max)(_Align, alignof(_Oversized_header)); if (_Bytes > SIZE_MAX - sizeof(_Oversized_header) - alignof(_Oversized_header) + 1) { // no room for header + alignment padding @@ -531,7 +531,7 @@ namespace pmr { // scale _Next_capacity by 2, saturating so that _Size_for_capacity(_Next_capacity) cannot overflow _Next_capacity = - _Min_value(_Next_capacity << 1, _Min_value((PTRDIFF_MAX - sizeof(_Chunk)) >> _Log_of_size, + (_STD min)(_Next_capacity << 1, (_STD min)((PTRDIFF_MAX - sizeof(_Chunk)) >> _Log_of_size, _Pool_resource._Options.max_blocks_per_chunk)); } }; @@ -559,7 +559,7 @@ namespace pmr { pair::iterator, unsigned char> _Find_pool( const size_t _Bytes, const size_t _Align) noexcept { // find the pool from which to allocate a block with size _Bytes and alignment _Align - const size_t _Size = _Max_value(_Bytes + sizeof(void*), _Align); + const size_t _Size = (_STD max)(_Bytes + sizeof(void*), _Align); const auto _Log_of_size = static_cast(_Ceiling_of_log_2(_Size)); return {_STD lower_bound(_Pools.begin(), _Pools.end(), _Log_of_size, [](const _Pool& _Al, const unsigned char _Log) { return _Al._Log_of_size < _Log; }), @@ -647,7 +647,7 @@ namespace pmr { // unscale _Next_buffer_size so the next allocation will be the same size as the most recent allocation // (keep synchronized with monotonic_buffer_resource::_Scale) const size_t _Unscaled = (_Next_buffer_size / 3 * 2 + alignof(_Header) - 1) & _Max_allocation; - _Next_buffer_size = _Max_value(_Unscaled, _Min_allocation); + _Next_buffer_size = (_STD max)(_Unscaled, _Min_allocation); _Intrusive_stack<_Header> _Tmp{}; _STD swap(_Tmp, _Chunks); @@ -730,7 +730,7 @@ namespace pmr { _New_size = (_Bytes + sizeof(_Header) + alignof(_Header) - 1) & _Max_allocation; } - const size_t _New_align = _Max_value(alignof(_Header), _Align); + const size_t _New_align = (_STD max)(alignof(_Header), _Align); void* _New_buffer = _Resource->allocate(_New_size, _New_align); _Check_alignment(_New_buffer, _New_align); diff --git a/stl/inc/numeric b/stl/inc/numeric index 59edecdf023..27b032b1f63 100644 --- a/stl/inc/numeric +++ b/stl/inc/numeric @@ -892,7 +892,7 @@ _NODISCARD constexpr common_type_t<_Mt, _Nt> gcd(const _Mt _Mx, const _Nt _Nx) n } const auto _Mx_trailing_zeroes = _Stl_bitscan_forward(_Mx_magnitude); - const auto _Common_factors_of_2 = _Min_value(_Mx_trailing_zeroes, _Stl_bitscan_forward(_Nx_magnitude)); + const auto _Common_factors_of_2 = (_STD min)(_Mx_trailing_zeroes, _Stl_bitscan_forward(_Nx_magnitude)); _Nx_magnitude >>= _Common_factors_of_2; _Mx_magnitude >>= _Mx_trailing_zeroes; do { diff --git a/stl/inc/sstream b/stl/inc/sstream index 2d9c445ed65..a96cc1c502d 100644 --- a/stl/inc/sstream +++ b/stl/inc/sstream @@ -86,7 +86,7 @@ public: _Mystr _Result(_Al); if (!(_Mystate & _Constant) && _Mysb::pptr()) { // writable, make string from write buffer const auto _Base = _Mysb::pbase(); - _Result.assign(_Base, static_cast<_Mysize_type>(_Max_value(_Mysb::pptr(), _Seekhigh) - _Base)); + _Result.assign(_Base, static_cast<_Mysize_type>((_STD max)(_Mysb::pptr(), _Seekhigh) - _Base)); } else if (!(_Mystate & _Noread) && _Mysb::gptr()) { // readable, make string from read buffer const auto _Base = _Mysb::eback(); _Result.assign(_Base, static_cast<_Mysize_type>(_Mysb::egptr() - _Base)); @@ -191,7 +191,7 @@ protected: return _Traits::eof(); } - const auto _Local_highwater = _Max_value(_Seekhigh, _Pptr); + const auto _Local_highwater = (_STD max)(_Seekhigh, _Pptr); if (_Local_highwater <= _Gptr) { // nothing in the put area to take return _Traits::eof(); } diff --git a/stl/inc/utility b/stl/inc/utility index 70bf9094009..862b405557f 100644 --- a/stl/inc/utility +++ b/stl/inc/utility @@ -23,19 +23,55 @@ _STL_DISABLE_CLANG_WARNINGS #undef new _STD_BEGIN -// FUNCTION TEMPLATE _Min_value -template -_Post_equal_to_(_Right < _Left ? _Right : _Left) constexpr const _Ty& _Min_value( - const _Ty& _Left, const _Ty& _Right) noexcept(noexcept(_Right < _Left)) { - return _Right < _Left ? _Right : _Left; +// FUNCTION TEMPLATE max +template +_NODISCARD constexpr const _Ty&(max)(const _Ty& _Left, const _Ty& _Right, _Pr _Pred) noexcept( + noexcept(_Pred(_Left, _Right))) /* strengthened */ { + // return larger of _Left and _Right using _Pred + return _Pred(_Left, _Right) ? _Right : _Left; } -// FUNCTION TEMPLATE _Max_value +#pragma warning(push) +#pragma warning(disable : 28285) // (syntax error in SAL annotation, occurs when _Ty is not an integral type) template -_Post_equal_to_(_Left < _Right ? _Right : _Left) constexpr const _Ty& _Max_value( - const _Ty& _Left, const _Ty& _Right) noexcept(noexcept(_Left < _Right)) { +_NODISCARD _Post_equal_to_(_Left < _Right ? _Right : _Left) constexpr const _Ty&(max)( + const _Ty& _Left, const _Ty& _Right) noexcept(noexcept(_Left < _Right)) /* strengthened */ { + // return larger of _Left and _Right return _Left < _Right ? _Right : _Left; } +#pragma warning(pop) + +template +_NODISCARD constexpr _Ty(max)(initializer_list<_Ty>, _Pr); // implemented in + +template +_NODISCARD constexpr _Ty(max)(initializer_list<_Ty>); // implemented in + + +// FUNCTION TEMPLATE min +template +_NODISCARD constexpr const _Ty&(min)(const _Ty& _Left, const _Ty& _Right, _Pr _Pred) noexcept( + noexcept(_Pred(_Right, _Left))) /* strengthened */ { + // return smaller of _Left and _Right using _Pred + return _Pred(_Right, _Left) ? _Right : _Left; +} + +#pragma warning(push) +#pragma warning(disable : 28285) // (syntax error in SAL annotation, occurs when _Ty is not an integral type) +template +_NODISCARD _Post_equal_to_(_Right < _Left ? _Right : _Left) constexpr const _Ty&(min)( + const _Ty& _Left, const _Ty& _Right) noexcept(noexcept(_Right < _Left)) /* strengthened */ { + // return smaller of _Left and _Right + return _Right < _Left ? _Right : _Left; +} +#pragma warning(pop) + +template +_NODISCARD constexpr _Ty(min)(initializer_list<_Ty>, _Pr); // implemented in + +template +_NODISCARD constexpr _Ty(min)(initializer_list<_Ty>); // implemented in + // FUNCTION TEMPLATE iter_swap (from ) template diff --git a/stl/inc/vector b/stl/inc/vector index f6e7de4f588..5f353c84912 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -1485,7 +1485,7 @@ public: } _NODISCARD size_type max_size() const noexcept { - return _Min_value( + return (_STD min)( static_cast((numeric_limits::max)()), _Alty_traits::max_size(_Getal())); } diff --git a/stl/inc/xhash b/stl/inc/xhash index 630cf4b4581..9a6ae4208b2 100644 --- a/stl/inc/xhash +++ b/stl/inc/xhash @@ -289,7 +289,7 @@ struct _Hash_vec { } _NODISCARD size_type max_size() const noexcept { - return _Min_value(static_cast((numeric_limits::max)()), + return (_STD min)(static_cast((numeric_limits::max)()), _Aliter_traits::max_size(_Mypair._Get_first())); } @@ -1050,7 +1050,7 @@ public: void rehash(size_type _Buckets) { // rebuild table with at least _Buckets buckets // don't violate a.bucket_count() >= a.size() / a.max_load_factor() invariant: - _Buckets = _Max_value(_Min_load_factor_buckets(_List.size()), _Buckets); + _Buckets = (_STD max)(_Min_load_factor_buckets(_List.size()), _Buckets); if (_Buckets <= _Maxidx) { // we already have enough buckets; nothing to do return; } @@ -1788,7 +1788,7 @@ protected: _NODISCARD size_type _Desired_grow_bucket_count(const size_type _For_size) const noexcept { const size_type _Old_buckets = bucket_count(); - const size_type _Req_buckets = _Max_value(_Min_buckets, _Min_load_factor_buckets(_For_size)); + const size_type _Req_buckets = (_STD max)(_Min_buckets, _Min_load_factor_buckets(_For_size)); if (_Old_buckets >= _Req_buckets) { // we already have enough buckets so there's no need to change the count return _Old_buckets; diff --git a/stl/inc/xlocale b/stl/inc/xlocale index c70fa05858d..9bfecaf1e3b 100644 --- a/stl/inc/xlocale +++ b/stl/inc/xlocale @@ -829,8 +829,8 @@ protected: // return p - _First1, for the largest value p in [_First1, _Last1] such that [_First1, p) successfully // converts to at most _Count _Elems // assumes 1:1 conversion - const auto _Dist = static_cast(_Min_value(_Last1 - _First1, ptrdiff_t{INT_MAX})); - return static_cast(_Min_value(_Count, _Dist)); + const auto _Dist = static_cast((_STD min)(_Last1 - _First1, ptrdiff_t{INT_MAX})); + return static_cast((_STD min)(_Count, _Dist)); } }; @@ -874,7 +874,7 @@ _NODISCARD int _Codecvt_do_length( if (_Result != codecvt_base::ok) { if (_Result == codecvt_base::noconv) { - _First1 += _Min_value(static_cast(_Last1 - _First1), _Count); + _First1 += (_STD min)(static_cast(_Last1 - _First1), _Count); } break; // error, noconv, or partial @@ -887,7 +887,7 @@ _NODISCARD int _Codecvt_do_length( _First1 = _Mid1; } - return static_cast(_Min_value(_First1 - _Old_first1, ptrdiff_t{INT_MAX})); + return static_cast((_STD min)(_First1 - _Old_first1, ptrdiff_t{INT_MAX})); } // ENUM _Codecvt_mode @@ -1710,7 +1710,7 @@ protected: _First1 = _Peek; } - return static_cast(_Min_value(_First1 - _Old_first1, ptrdiff_t{INT_MAX})); + return static_cast((_STD min)(_First1 - _Old_first1, ptrdiff_t{INT_MAX})); } virtual bool __CLR_OR_THIS_CALL do_always_noconv() const noexcept override { @@ -1953,7 +1953,7 @@ protected: _First1 = _Peek; } - return static_cast(_Min_value(_First1 - _Old_first1, ptrdiff_t{INT_MAX})); + return static_cast((_STD min)(_First1 - _Old_first1, ptrdiff_t{INT_MAX})); } virtual bool __CLR_OR_THIS_CALL do_always_noconv() const noexcept override { @@ -2150,7 +2150,7 @@ protected: _First1 += _Bytes; } - return static_cast(_Min_value(_First1 - _Old_first1, ptrdiff_t{INT_MAX})); + return static_cast((_STD min)(_First1 - _Old_first1, ptrdiff_t{INT_MAX})); } virtual bool __CLR_OR_THIS_CALL do_always_noconv() const noexcept override { @@ -2352,7 +2352,7 @@ protected: _First1 += _Bytes; } - return static_cast(_Min_value(_First1 - _Old_first1, ptrdiff_t{INT_MAX})); + return static_cast((_STD min)(_First1 - _Old_first1, ptrdiff_t{INT_MAX})); } virtual bool __CLR_OR_THIS_CALL do_always_noconv() const noexcept override { diff --git a/stl/inc/xlocinfo b/stl/inc/xlocinfo index b1e8d2187d0..c22a8dcd9df 100644 --- a/stl/inc/xlocinfo +++ b/stl/inc/xlocinfo @@ -52,6 +52,88 @@ private: void* _Timeptr; // pointer to time information }; +// CLASS TEMPLATE _Yarn +template +class _CRTIMP2_PURE_IMPORT _Yarn { // wrap a NTCTS +public: + __CLR_OR_THIS_CALL _Yarn() noexcept : _Myptr(nullptr), _Nul(0) {} + + __CLR_OR_THIS_CALL _Yarn(const _Yarn& _Right) noexcept : _Myptr(nullptr), _Nul(0) { + *this = _Right; + } + + __CLR_OR_THIS_CALL _Yarn(const _Elem* _Right) noexcept : _Myptr(nullptr), _Nul(0) { + *this = _Right; + } + + _Yarn& __CLR_OR_THIS_CALL operator=(const _Yarn& _Right) noexcept { + return *this = _Right._Myptr; + } + + _Yarn& __CLR_OR_THIS_CALL operator=(const _Elem* _Right) noexcept { + if (_Myptr != _Right) { // new value, discard old and copy new + _Tidy(); + + if (_Right) { // new is not empty, copy it + const _Elem* _Ptr = _Right; + while (*_Ptr != _Elem{}) { + ++_Ptr; + } + + const auto _Count = (++_Ptr - _Right) * sizeof(_Elem); + +#ifdef _DEBUG + _Myptr = static_cast<_Elem*>(_malloc_dbg(_Count, _CRT_BLOCK, __FILE__, __LINE__)); +#else // _DEBUG + _Myptr = static_cast<_Elem*>(_CSTD malloc(_Count)); +#endif // _DEBUG + + if (_Myptr) { + _CSTD memcpy(_Myptr, _Right, _Count); + } + } + } + + return *this; + } + + __CLR_OR_THIS_CALL ~_Yarn() noexcept { + _Tidy(); + } + + _NODISCARD bool __CLR_OR_THIS_CALL empty() const noexcept { + return _Myptr == nullptr; + } + + _Ret_z_ const _Elem* __CLR_OR_THIS_CALL c_str() const noexcept { + return _Myptr ? _Myptr : &_Nul; + } + + _NODISCARD bool __CLR_OR_THIS_CALL _Empty() const noexcept { + return _Myptr == nullptr; + } + + _Ret_z_ const _Elem* __CLR_OR_THIS_CALL _C_str() const noexcept { + return _Myptr ? _Myptr : &_Nul; + } + +private: + void __CLR_OR_THIS_CALL _Tidy() noexcept { + if (_Myptr) { +#ifdef _DEBUG + _free_dbg(_Myptr, _CRT_BLOCK); +#else // _DEBUG + _CSTD free(_Myptr); +#endif // _DEBUG + } + + _Myptr = nullptr; + } + + _Elem* _Myptr; // pointer to allocated string + _Elem _Nul; // nul terminator for unallocated string +}; + // CLASS _Locinfo class _CRTIMP2_PURE_IMPORT _Locinfo { // summary of all stuff specific to a locale used by standard facets public: diff --git a/stl/inc/xmemory b/stl/inc/xmemory index e4ef91cb23f..e86c7ccb9b2 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -23,6 +23,33 @@ _STL_DISABLE_CLANG_WARNINGS #undef new _STD_BEGIN +// STRUCT TEMPLATE _Tidy_guard +template +struct _Tidy_guard { // class with destructor that calls _Tidy + _Ty* _Target; + ~_Tidy_guard() { + if (_Target) { + _Target->_Tidy(); + } + } +}; + +// STRUCT TEMPLATE _Tidy_deallocate_guard +template +struct _Tidy_deallocate_guard { // class with destructor that calls _Tidy_deallocate + _Ty* _Target; + ~_Tidy_deallocate_guard() { + if (_Target) { + _Target->_Tidy_deallocate(); + } + } +}; + +// VARIABLE TEMPLATE _Nothrow_compare +template +_INLINE_VAR constexpr bool _Nothrow_compare = noexcept( + static_cast(_STD declval()(_STD declval(), _STD declval()))); + // FUNCTION TEMPLATE _Get_size_of_n template _NODISCARD constexpr size_t _Get_size_of_n(const size_t _Count) { @@ -41,7 +68,7 @@ _NODISCARD constexpr size_t _Get_size_of_n(const size_t _Count) { // VARIABLE TEMPLATE _New_alignof template -_INLINE_VAR constexpr size_t _New_alignof = _Max_value(alignof(_Ty), +_INLINE_VAR constexpr size_t _New_alignof = (_STD max)(alignof(_Ty), static_cast(__STDCPP_DEFAULT_NEW_ALIGNMENT__) // TRANSITION, VSO-522105 ); @@ -141,7 +168,7 @@ _DECLSPEC_ALLOCATOR void* _Allocate(const size_t _Bytes) { #if defined(_M_IX86) || defined(_M_X64) if (_Bytes >= _Big_allocation_threshold) { // boost the alignment of big allocations to help autovectorization - _Passed_align = _Max_value(_Align, _Big_allocation_alignment); + _Passed_align = (_STD max)(_Align, _Big_allocation_alignment); } #endif // defined(_M_IX86) || defined(_M_X64) @@ -154,7 +181,7 @@ void _Deallocate(void* _Ptr, const size_t _Bytes) noexcept { size_t _Passed_align = _Align; #if defined(_M_IX86) || defined(_M_X64) if (_Bytes >= _Big_allocation_threshold) { // boost the alignment of big allocations to help autovectorization - _Passed_align = _Max_value(_Align, _Big_allocation_alignment); + _Passed_align = (_STD max)(_Align, _Big_allocation_alignment); } #endif // defined(_M_IX86) || defined(_M_X64) diff --git a/stl/inc/xstring b/stl/inc/xstring index 169f0ddbd4a..50122487ab2 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -513,7 +513,7 @@ template constexpr int _Traits_compare(_In_reads_(_Left_size) const _Traits_ptr_t<_Traits> _Left, const size_t _Left_size, _In_reads_(_Right_size) const _Traits_ptr_t<_Traits> _Right, const size_t _Right_size) noexcept { // compare [_Left, _Left + _Left_size) to [_Right, _Right + _Right_size) using _Traits - const int _Ans = _Traits::compare(_Left, _Right, _Min_value(_Left_size, _Right_size)); + const int _Ans = _Traits::compare(_Left, _Right, (_STD min)(_Left_size, _Right_size)); if (_Ans != 0) { return _Ans; @@ -584,11 +584,11 @@ constexpr size_t _Traits_rfind(_In_reads_(_Hay_size) const _Traits_ptr_t<_Traits const size_t _Needle_size) noexcept { // search [_Haystack, _Haystack + _Hay_size) for [_Needle, _Needle + _Needle_size) beginning before _Start_at if (_Needle_size == 0) { - return _Min_value(_Start_at, _Hay_size); // empty string always matches + return (_STD min)(_Start_at, _Hay_size); // empty string always matches } if (_Needle_size <= _Hay_size) { // room for match, look for it - for (auto _Match_try = _Haystack + _Min_value(_Start_at, _Hay_size - _Needle_size);; --_Match_try) { + for (auto _Match_try = _Haystack + (_STD min)(_Start_at, _Hay_size - _Needle_size);; --_Match_try) { if (_Traits::eq(*_Match_try, *_Needle) && _Traits::compare(_Match_try, _Needle, _Needle_size) == 0) { return static_cast(_Match_try - _Haystack); // found a match } @@ -607,7 +607,7 @@ constexpr size_t _Traits_rfind_ch(_In_reads_(_Hay_size) const _Traits_ptr_t<_Tra const size_t _Start_at, const _Traits_ch_t<_Traits> _Ch) noexcept { // search [_Haystack, _Haystack + _Hay_size) for _Ch before _Start_at if (_Hay_size != 0) { // room for match, look for it - for (auto _Match_try = _Haystack + _Min_value(_Start_at, _Hay_size - 1);; --_Match_try) { + for (auto _Match_try = _Haystack + (_STD min)(_Start_at, _Hay_size - 1);; --_Match_try) { if (_Traits::eq(*_Match_try, _Ch)) { return static_cast(_Match_try - _Haystack); // found a match } @@ -721,7 +721,7 @@ constexpr size_t _Traits_find_last_of(_In_reads_(_Hay_size) const _Traits_ptr_t< // in [_Haystack, _Haystack + _Hay_size), look for last of [_Needle, _Needle + _Needle_size), before _Start_at // general algorithm if (_Needle_size != 0 && _Hay_size != 0) { // worth searching, do it - for (auto _Match_try = _Haystack + _Min_value(_Start_at, _Hay_size - 1);; --_Match_try) { + for (auto _Match_try = _Haystack + (_STD min)(_Start_at, _Hay_size - 1);; --_Match_try) { if (_Traits::find(_Needle, _Needle_size, *_Match_try)) { return static_cast(_Match_try - _Haystack); // found a match } @@ -748,7 +748,7 @@ constexpr size_t _Traits_find_last_of(_In_reads_(_Hay_size) const _Traits_ptr_t< return _Traits_find_last_of<_Traits>(_Haystack, _Hay_size, _Start_at, _Needle, _Needle_size, false_type{}); } - for (auto _Match_try = _Haystack + _Min_value(_Start_at, _Hay_size - 1);; --_Match_try) { + for (auto _Match_try = _Haystack + (_STD min)(_Start_at, _Hay_size - 1);; --_Match_try) { if (_Matches._Match(*_Match_try)) { return static_cast(_Match_try - _Haystack); // found a match } @@ -828,7 +828,7 @@ constexpr size_t _Traits_find_last_not_of(_In_reads_(_Hay_size) const _Traits_pt // in [_Haystack, _Haystack + _Hay_size), look for none of [_Needle, _Needle + _Needle_size), before _Start_at // general algorithm if (_Hay_size != 0) { // worth searching, do it - for (auto _Match_try = _Haystack + _Min_value(_Start_at, _Hay_size - 1);; --_Match_try) { + for (auto _Match_try = _Haystack + (_STD min)(_Start_at, _Hay_size - 1);; --_Match_try) { if (!_Traits::find(_Needle, _Needle_size, *_Match_try)) { return static_cast(_Match_try - _Haystack); // found a match } @@ -856,7 +856,7 @@ constexpr size_t _Traits_find_last_not_of(_In_reads_(_Hay_size) const _Traits_pt _Haystack, _Hay_size, _Start_at, _Needle, _Needle_size, false_type{}); } - for (auto _Match_try = _Haystack + _Min_value(_Start_at, _Hay_size - 1);; --_Match_try) { + for (auto _Match_try = _Haystack + (_STD min)(_Start_at, _Hay_size - 1);; --_Match_try) { if (!_Matches._Match(*_Match_try)) { return static_cast(_Match_try - _Haystack); // found a match } @@ -875,7 +875,7 @@ constexpr size_t _Traits_rfind_not_ch(_In_reads_(_Hay_size) const _Traits_ptr_t< const size_t _Hay_size, const size_t _Start_at, const _Traits_ch_t<_Traits> _Ch) noexcept { // search [_Haystack, _Haystack + _Hay_size) for any value other than _Ch before _Start_at if (_Hay_size != 0) { // room for match, look for it - for (auto _Match_try = _Haystack + _Min_value(_Start_at, _Hay_size - 1);; --_Match_try) { + for (auto _Match_try = _Haystack + (_STD min)(_Start_at, _Hay_size - 1);; --_Match_try) { if (!_Traits::eq(*_Match_try, _Ch)) { return static_cast(_Match_try - _Haystack); // found a match } @@ -1255,7 +1255,7 @@ public: _NODISCARD constexpr size_type max_size() const noexcept { // bound to PTRDIFF_MAX to make end() - begin() well defined (also makes room for npos) // bound to static_cast(-1) / sizeof(_Elem) by address space limits - return _Min_value(static_cast(PTRDIFF_MAX), static_cast(-1) / sizeof(_Elem)); + return (_STD min)(static_cast(PTRDIFF_MAX), static_cast(-1) / sizeof(_Elem)); } _NODISCARD constexpr const_reference operator[](const size_type _Off) const noexcept /* strengthened */ { @@ -1562,7 +1562,7 @@ private: constexpr size_type _Clamp_suffix_size(const size_type _Off, const size_type _Size) const noexcept { // trims _Size to the longest it can be assuming a string at/after _Off - return _Min_value(_Size, _Mysize - _Off); + return (_STD min)(_Size, _Mysize - _Off); } [[noreturn]] static void _Xran() { @@ -2174,7 +2174,7 @@ public: size_type _Clamp_suffix_size(const size_type _Off, const size_type _Size) const noexcept { // trims _Size to the longest it can be assuming a string at/after _Off - return _Min_value(_Size, _Mysize - _Off); + return (_STD min)(_Size, _Mysize - _Off); } union _Bxty { // storage for small buffer or pointer to larger one @@ -2668,7 +2668,7 @@ private: } auto& _Al = _Getal(); - const size_type _New_capacity = _Min_value(_Right_size | _ALLOC_MASK, max_size()); + const size_type _New_capacity = (_STD min)(_Right_size | _ALLOC_MASK, max_size()); const pointer _New_array = _Al.allocate(_New_capacity + 1); // throws _Construct_in_place(_My_data._Bx._Ptr, _New_array); _Traits::copy(_Unfancy(_New_array), _Right_ptr, _Right_size + 1); @@ -3567,7 +3567,7 @@ public: return; } - const size_type _Target_capacity = _Min_value(_My_data._Mysize | _ALLOC_MASK, max_size()); + const size_type _Target_capacity = (_STD min)(_My_data._Mysize | _ALLOC_MASK, max_size()); if (_Target_capacity < _My_data._Myres) { // worth shrinking, do it auto& _Al = _Getal(); const pointer _New_ptr = _Al.allocate(_Target_capacity + 1); // throws @@ -3695,8 +3695,8 @@ public: _NODISCARD size_type max_size() const noexcept { const size_type _Alloc_max = _Alty_traits::max_size(_Getal()); const size_type _Storage_max = // can always store small string - _Max_value(_Alloc_max, static_cast(_BUF_SIZE)); - return _Min_value(static_cast((numeric_limits::max)()), + (_STD max)(_Alloc_max, static_cast(_BUF_SIZE)); + return (_STD min)(static_cast((numeric_limits::max)()), _Storage_max - 1 // -1 is for null terminator and/or npos ); } @@ -4213,7 +4213,7 @@ private: return _Max; } - return _Max_value(_Masked, _Old + _Old / 2); + return (_STD max)(_Masked, _Old + _Old / 2); } _NODISCARD size_type _Calculate_growth(const size_type _Requested) const noexcept { diff --git a/stl/inc/xtree b/stl/inc/xtree index e9c0b2d9db6..9357cdb57ca 100644 --- a/stl/inc/xtree +++ b/stl/inc/xtree @@ -1306,7 +1306,7 @@ public: } _NODISCARD size_type max_size() const noexcept { - return _Min_value( + return (_STD min)( static_cast((numeric_limits::max)()), _Alnode_traits::max_size(_Getal())); } diff --git a/stl/inc/xutility b/stl/inc/xutility index 2ad68ddc4e6..755fec5c71f 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -21,7 +21,13 @@ _STL_DISABLE_CLANG_WARNINGS #pragma push_macro("new") #undef new -#if (defined(_M_IX86) || defined(_M_X64)) && !defined(_M_CEE_PURE) +#if (defined(_M_IX86) || defined(_M_X64)) && !defined(_M_CEE_PURE) && !defined(_M_HYBRID) +#define _USE_STD_VECTOR_ALGORITHMS 1 +#else +#define _USE_STD_VECTOR_ALGORITHMS 0 +#endif + +#if _USE_STD_VECTOR_ALGORITHMS _EXTERN_C // The "noalias" attribute tells the compiler optimizer that pointers going into these hand-vectorized algorithms // won't be stored beyond the lifetime of the function, and that the function will only reference arrays denoted by @@ -34,8 +40,10 @@ __declspec(noalias) void __cdecl __std_reverse_trivially_swappable_1(void* _Firs __declspec(noalias) void __cdecl __std_reverse_trivially_swappable_2(void* _First, void* _Last) noexcept; __declspec(noalias) void __cdecl __std_reverse_trivially_swappable_4(void* _First, void* _Last) noexcept; __declspec(noalias) void __cdecl __std_reverse_trivially_swappable_8(void* _First, void* _Last) noexcept; +__declspec(noalias) void __cdecl __std_swap_ranges_trivially_swappable_noalias( + void* _First1, void* _Last1, void* _First2) noexcept; _END_EXTERN_C -#endif // (defined(_M_IX86) || defined(_M_X64)) && !defined(_M_CEE_PURE) +#endif // _USE_STD_VECTOR_ALGORITHMS _STD_BEGIN @@ -4970,7 +4978,7 @@ _CONSTEXPR20 void reverse(const _BidIt _First, const _BidIt _Last) { // reverse _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); auto _ULast = _Get_unwrapped(_Last); -#if (defined(_M_IX86) || defined(_M_X64)) && !defined(_M_CEE_PURE) && !defined(_M_HYBRID) +#if _USE_STD_VECTOR_ALGORITHMS using _Elem = remove_pointer_t; constexpr bool _Allow_vectorization = conjunction_v, _Is_trivially_swappable<_Elem>, negation>>; @@ -5008,7 +5016,7 @@ _CONSTEXPR20 void reverse(const _BidIt _First, const _BidIt _Last) { // reverse return; } } -#endif // (defined(_M_IX86) || defined(_M_X64)) && !defined(_M_CEE_PURE) && !defined(_M_HYBRID) +#endif // _USE_STD_VECTOR_ALGORITHMS for (; _UFirst != _ULast && _UFirst != --_ULast; ++_UFirst) { _STD iter_swap(_UFirst, _ULast); @@ -5023,7 +5031,7 @@ void _Reverse_unchecked1(_BidIt _First, _BidIt _Last, integral_constant void _Reverse_unchecked1(const _BidIt _First, const _BidIt _Last, integral_constant) { // reverse elements in [_First, _Last), pointers to trivially swappable of size 1 @@ -5047,12 +5055,12 @@ void _Reverse_unchecked1(const _BidIt _First, const _BidIt _Last, integral_const // reverse elements in [_First, _Last), pointers to trivially swappable of size 8 __std_reverse_trivially_swappable_8(_First, _Last); } -#endif // (defined(_M_IX86) || defined(_M_X64)) && !defined(_M_CEE_PURE) && !defined(_M_HYBRID) +#endif // _USE_STD_VECTOR_ALGORITHMS template void _Reverse_unchecked(const _BidIt _First, const _BidIt _Last) { // reverse elements in [_First, _Last), choose optimization -#if (defined(_M_IX86) || defined(_M_X64)) && !defined(_M_CEE_PURE) && !defined(_M_HYBRID) +#if _USE_STD_VECTOR_ALGORITHMS using _Elem = remove_pointer_t<_BidIt>; constexpr size_t _Opt = is_pointer_v<_BidIt> // @@ -5063,7 +5071,7 @@ void _Reverse_unchecked(const _BidIt _First, const _BidIt _Last) { : 0; #else // ^^^ vectorize / no vectorize vvv constexpr size_t _Opt = 0; -#endif // (defined(_M_IX86) || defined(_M_X64)) && !defined(_M_CEE_PURE) && !defined(_M_HYBRID) +#endif // _USE_STD_VECTOR_ALGORITHMS _Reverse_unchecked1(_First, _Last, integral_constant{}); } @@ -5273,6 +5281,37 @@ _NODISCARD _CONSTEXPR20 _FwdIt lower_bound(_FwdIt _First, _FwdIt _Last, const _T return _STD lower_bound(_First, _Last, _Val, less<>()); } +// FUNCTION TEMPLATE _Swap_ranges_unchecked +template +_CONSTEXPR20 _FwdIt2 _Swap_ranges_unchecked(_FwdIt1 _First1, const _FwdIt1 _Last1, _FwdIt2 _First2) { + // swap [_First1, _Last1) with [_First2, ...), no special optimization + for (; _First1 != _Last1; ++_First1, (void) ++_First2) { + _STD iter_swap(_First1, _First2); + } + + return _First2; +} + +#if _USE_STD_VECTOR_ALGORITHMS +template , int> = 0> +_CONSTEXPR20 _Ty* _Swap_ranges_unchecked(_Ty* _First1, _Ty* const _Last1, _Ty* _First2) { + // swap [_First1, _Last1) with [_First2, ...), trivially swappable optimization +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + __std_swap_ranges_trivially_swappable_noalias(_First1, _Last1, _First2); + return _First2 + (_Last1 - _First1); + } + + for (; _First1 != _Last1; ++_First1, (void) ++_First2) { + _STD iter_swap(_First1, _First2); + } + + return _First2; +} +#endif // _USE_STD_VECTOR_ALGORITHMS + // CLASS TEMPLATE _Rng_from_urng template class _Rng_from_urng { // wrap a URNG as an RNG @@ -5340,137 +5379,6 @@ private: _Udiff _Bmask; // 2^_Bits - 1 }; -// CLASS TEMPLATE _Yarn -template -class _CRTIMP2_PURE_IMPORT _Yarn { // wrap a NTCTS -public: - __CLR_OR_THIS_CALL _Yarn() noexcept : _Myptr(nullptr), _Nul(0) {} - - __CLR_OR_THIS_CALL _Yarn(const _Yarn& _Right) noexcept : _Myptr(nullptr), _Nul(0) { - *this = _Right; - } - - __CLR_OR_THIS_CALL _Yarn(const _Elem* _Right) noexcept : _Myptr(nullptr), _Nul(0) { - *this = _Right; - } - - _Yarn& __CLR_OR_THIS_CALL operator=(const _Yarn& _Right) noexcept { - return *this = _Right._Myptr; - } - - _Yarn& __CLR_OR_THIS_CALL operator=(const _Elem* _Right) noexcept { - if (_Myptr != _Right) { // new value, discard old and copy new - _Tidy(); - - if (_Right) { // new is not empty, copy it - const _Elem* _Ptr = _Right; - while (*_Ptr != _Elem{}) { - ++_Ptr; - } - - const auto _Count = (++_Ptr - _Right) * sizeof(_Elem); - -#ifdef _DEBUG - _Myptr = static_cast<_Elem*>(_malloc_dbg(_Count, _CRT_BLOCK, __FILE__, __LINE__)); -#else // _DEBUG - _Myptr = static_cast<_Elem*>(_CSTD malloc(_Count)); -#endif // _DEBUG - - if (_Myptr) { - _CSTD memcpy(_Myptr, _Right, _Count); - } - } - } - - return *this; - } - - __CLR_OR_THIS_CALL ~_Yarn() noexcept { - _Tidy(); - } - - _NODISCARD bool __CLR_OR_THIS_CALL empty() const noexcept { - return _Myptr == nullptr; - } - - _Ret_z_ const _Elem* __CLR_OR_THIS_CALL c_str() const noexcept { - return _Myptr ? _Myptr : &_Nul; - } - - _NODISCARD bool __CLR_OR_THIS_CALL _Empty() const noexcept { - return _Myptr == nullptr; - } - - _Ret_z_ const _Elem* __CLR_OR_THIS_CALL _C_str() const noexcept { - return _Myptr ? _Myptr : &_Nul; - } - -private: - void __CLR_OR_THIS_CALL _Tidy() noexcept { - if (_Myptr) { -#ifdef _DEBUG - _free_dbg(_Myptr, _CRT_BLOCK); -#else // _DEBUG - _CSTD free(_Myptr); -#endif // _DEBUG - } - - _Myptr = nullptr; - } - - _Elem* _Myptr; // pointer to allocated string - _Elem _Nul; // nul terminator for unallocated string -}; - - -// CLASS TEMPLATE back_insert_iterator -template -class back_insert_iterator { // wrap pushes to back of container as output iterator -public: - using iterator_category = output_iterator_tag; - using value_type = void; - using difference_type = void; - using pointer = void; - using reference = void; - - using container_type = _Container; - - explicit back_insert_iterator(_Container& _Cont) noexcept /* strengthened */ : container(_STD addressof(_Cont)) {} - - back_insert_iterator& operator=(const typename _Container::value_type& _Val) { - container->push_back(_Val); - return *this; - } - - back_insert_iterator& operator=(typename _Container::value_type&& _Val) { - container->push_back(_STD move(_Val)); - return *this; - } - - _NODISCARD back_insert_iterator& operator*() noexcept /* strengthened */ { - return *this; - } - - back_insert_iterator& operator++() noexcept /* strengthened */ { - return *this; - } - - back_insert_iterator operator++(int) noexcept /* strengthened */ { - return *this; - } - -protected: - _Container* container; // pointer to container -}; - -// FUNCTION TEMPLATE back_inserter -template -_NODISCARD back_insert_iterator<_Container> back_inserter(_Container& _Cont) noexcept /* strengthened */ { - // return a back_insert_iterator - return back_insert_iterator<_Container>(_Cont); -} - - // STRUCT TEMPLATE _Has_allocator_type template struct _Has_allocator_type : false_type { // tests for suitable _Ty::allocator_type @@ -5513,33 +5421,6 @@ struct _CXX17_DEPRECATE_ITERATOR_BASE_CLASS iterator { // base type for iterator using pointer = _Pointer; using reference = _Reference; }; - -// STRUCT TEMPLATE _Tidy_guard -template -struct _Tidy_guard { // class with destructor that calls _Tidy - _Ty* _Target; - ~_Tidy_guard() { - if (_Target) { - _Target->_Tidy(); - } - } -}; - -// STRUCT TEMPLATE _Tidy_deallocate_guard -template -struct _Tidy_deallocate_guard { // class with destructor that calls _Tidy_deallocate - _Ty* _Target; - ~_Tidy_deallocate_guard() { - if (_Target) { - _Target->_Tidy_deallocate(); - } - } -}; - -// VARIABLE TEMPLATE _Nothrow_compare -template -_INLINE_VAR constexpr bool _Nothrow_compare = noexcept( - static_cast(_STD declval()(_STD declval(), _STD declval()))); _STD_END #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS diff --git a/stl/src/excptptr.cpp b/stl/src/excptptr.cpp index 28dbeb0fc7b..f8ae40a7668 100644 --- a/stl/src/excptptr.cpp +++ b/stl/src/excptptr.cpp @@ -90,7 +90,7 @@ namespace { // copy the number of parameters in use constexpr auto _Max_parameters = static_cast(EXCEPTION_MAXIMUM_PARAMETERS); - const auto _In_use = _Min_value(_Parameters, _Max_parameters); + const auto _In_use = (_STD min)(_Parameters, _Max_parameters); _CSTD memcpy(_Dest.ExceptionInformation, _Src.ExceptionInformation, _In_use * sizeof(ULONG_PTR)); _CSTD memset(&_Dest.ExceptionInformation[_In_use], 0, (_Max_parameters - _In_use) * sizeof(ULONG_PTR)); }