Skip to content

Commit

Permalink
ADL-proof implementation of [alg.min.max], [alg.clamp], [alg.lex.comp…
Browse files Browse the repository at this point in the history
…arison], and [alg.three.way] (#4216)

Co-authored-by: Stephan T. Lavavej <[email protected]>
  • Loading branch information
frederick-vs-ja and StephanTLavavej authored Dec 7, 2023
1 parent 0403d19 commit 8286d8e
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 76 deletions.
45 changes: 24 additions & 21 deletions stl/inc/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@ _STD pair<_Ty*, _Ty*> __std_minmax_element(_Ty* _First, _Ty* _Last) noexcept {
_Min_max_element_t _Res;

if constexpr (sizeof(_Ty) == 1) {
_Res = __std_minmax_element_1(_First, _Last, _Signed);
_Res = ::__std_minmax_element_1(_First, _Last, _Signed);
} else if constexpr (sizeof(_Ty) == 2) {
_Res = __std_minmax_element_2(_First, _Last, _Signed);
_Res = ::__std_minmax_element_2(_First, _Last, _Signed);
} else if constexpr (sizeof(_Ty) == 4) {
_Res = __std_minmax_element_4(_First, _Last, _Signed);
_Res = ::__std_minmax_element_4(_First, _Last, _Signed);
} else if constexpr (sizeof(_Ty) == 8) {
_Res = __std_minmax_element_8(_First, _Last, _Signed);
_Res = ::__std_minmax_element_8(_First, _Last, _Signed);
} else {
static_assert(_STD _Always_false<_Ty>, "Unexpected size");
}
Expand Down Expand Up @@ -9729,8 +9729,8 @@ constexpr pair<_FwdIt, _FwdIt> _Minmax_element_unchecked(_FwdIt _First, _FwdIt _
#if _USE_STD_VECTOR_ALGORITHMS
if constexpr (_Is_min_max_optimization_safe<_FwdIt, _Pr>) {
if (!_Is_constant_evaluated()) {
const auto _First_ptr = _To_address(_First);
const auto _Result = _STD __std_minmax_element(_First_ptr, _To_address(_Last));
const auto _First_ptr = _STD _To_address(_First);
const auto _Result = _STD __std_minmax_element(_First_ptr, _STD _To_address(_Last));
if constexpr (is_pointer_v<_FwdIt>) {
return _Result;
} else {
Expand Down Expand Up @@ -9781,10 +9781,11 @@ constexpr pair<_FwdIt, _FwdIt> _Minmax_element_unchecked(_FwdIt _First, _FwdIt _
_EXPORT_STD template <class _FwdIt, class _Pr>
_NODISCARD constexpr pair<_FwdIt, _FwdIt> minmax_element(_FwdIt _First, _FwdIt _Last, _Pr _Pred) {
// find smallest and largest elements
_Adl_verify_range(_First, _Last);
const auto _Result = _STD _Minmax_element_unchecked(_Get_unwrapped(_First), _Get_unwrapped(_Last), _Pass_fn(_Pred));
_Seek_wrapped(_Last, _Result.second);
_Seek_wrapped(_First, _Result.first);
_STD _Adl_verify_range(_First, _Last);
const auto _Result =
_STD _Minmax_element_unchecked(_STD _Get_unwrapped(_First), _STD _Get_unwrapped(_Last), _STD _Pass_fn(_Pred));
_STD _Seek_wrapped(_Last, _Result.second);
_STD _Seek_wrapped(_First, _Result.first);
return {_First, _Last};
}

Expand All @@ -9801,7 +9802,7 @@ _NODISCARD pair<_FwdIt, _FwdIt> minmax_element(_ExPo&&, _FwdIt _First, _FwdIt _L
// find smallest and largest elements
// not parallelized at present, parallelism expected to be feasible in a future release
_REQUIRE_PARALLEL_ITERATOR(_FwdIt);
return _STD minmax_element(_First, _Last, _Pass_fn(_Pred));
return _STD minmax_element(_First, _Last, _STD _Pass_fn(_Pred));
}

_EXPORT_STD template <class _ExPo, class _FwdIt, _Enable_if_execution_policy_t<_ExPo> = 0>
Expand Down Expand Up @@ -9838,8 +9839,8 @@ namespace ranges {
_Rng&& _Range, _Pr _Pred = {}, _Pj _Proj = {}) const {
auto _UResult = _Minmax_element_fwd_unchecked(
_RANGES _Ubegin(_Range), _RANGES _Uend(_Range), _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj));
return {
_Rewrap_iterator(_Range, _STD move(_UResult.min)), _Rewrap_iterator(_Range, _STD move(_UResult.max))};
return {_RANGES _Rewrap_iterator(_Range, _STD move(_UResult.min)),
_RANGES _Rewrap_iterator(_Range, _STD move(_UResult.max))};
}

private:
Expand Down Expand Up @@ -9929,7 +9930,8 @@ _NODISCARD constexpr pair<const _Ty&, const _Ty&> minmax(const _Ty& _Left _MSVC_
_EXPORT_STD template <class _Ty, class _Pr>
_NODISCARD constexpr pair<_Ty, _Ty> minmax(initializer_list<_Ty> _Ilist, _Pr _Pred) {
// return {leftmost/smallest, rightmost/largest}
pair<const _Ty*, const _Ty*> _Res = _STD _Minmax_element_unchecked(_Ilist.begin(), _Ilist.end(), _Pass_fn(_Pred));
pair<const _Ty*, const _Ty*> _Res =
_STD _Minmax_element_unchecked(_Ilist.begin(), _Ilist.end(), _STD _Pass_fn(_Pred));
return pair<_Ty, _Ty>(*_Res.first, *_Res.second);
}

Expand Down Expand Up @@ -10498,12 +10500,13 @@ namespace ranges {
indirect_strict_weak_order<projected<_It1, _Pj1>, projected<_It2, _Pj2>> _Pr = ranges::less>
_NODISCARD constexpr bool operator()(_It1 _First1, _Se1 _Last1, _It2 _First2, _Se2 _Last2, _Pr _Pred = {},
_Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const {
_Adl_verify_range(_First1, _Last1);
_Adl_verify_range(_First2, _Last2);
_STD _Adl_verify_range(_First1, _Last1);
_STD _Adl_verify_range(_First2, _Last2);

return _Lexicographical_compare_unchecked(_Unwrap_iter<_Se1>(_STD move(_First1)),
_Unwrap_sent<_It1>(_STD move(_Last1)), _Unwrap_iter<_Se2>(_STD move(_First2)),
_Unwrap_sent<_It2>(_STD move(_Last2)), _Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2));
return _Lexicographical_compare_unchecked(_RANGES _Unwrap_iter<_Se1>(_STD move(_First1)),
_RANGES _Unwrap_sent<_It1>(_STD move(_Last1)), _RANGES _Unwrap_iter<_Se2>(_STD move(_First2)),
_RANGES _Unwrap_sent<_It2>(_STD move(_Last2)), _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj1),
_STD _Pass_fn(_Proj2));
}

template <input_range _Rng1, input_range _Rng2, class _Pj1 = identity, class _Pj2 = identity,
Expand All @@ -10512,7 +10515,7 @@ namespace ranges {
_NODISCARD constexpr bool operator()(
_Rng1&& _Range1, _Rng2&& _Range2, _Pr _Pred = {}, _Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const {
return _Lexicographical_compare_unchecked(_Ubegin(_Range1), _Uend(_Range1), _Ubegin(_Range2),
_Uend(_Range2), _Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2));
_Uend(_Range2), _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj1), _STD _Pass_fn(_Proj2));
}

private:
Expand Down Expand Up @@ -10546,7 +10549,7 @@ namespace ranges {
_Num2 = SIZE_MAX;
}

const int _Ans = _Memcmp_count(_First1, _First2, (_STD min)(_Num1, _Num2));
const int _Ans = _STD _Memcmp_count(_First1, _First2, (_STD min)(_Num1, _Num2));
return _Memcmp_classification_pred{}(_Ans, 0) || (_Ans == 0 && _Num1 < _Num2);
}
}
Expand Down
Loading

0 comments on commit 8286d8e

Please sign in to comment.