<algorithm>: ranges::minmax should dereference iterators only once - #3366
Conversation
<algorithm>: ranges::minmax should dereference iterators only once
Co-authored-by: Nicole Mazzuca <mazzucan@outlook.com>
Co-authored-by: Alex Guteniev <gutenev@gmail.com> Co-authored-by: timsong-cpp <rs2740@gmail.com>
This comment was marked as resolved.
This comment was marked as resolved.
|
This new pattern is unusual, but I rate it only 2 squirrels out of 5. (The Standard has an example, WG21-N4928 [dcl.init.aggr]/6, where a default member initializer refers to previous members, that's at least 3 squirrels.) I probably would have commented it, but I don't think it's worth resetting testing again. It does seem to be an improvement compared to the previous version, thanks! |
Good, I found it there: libc++ also has the bug, I created: https://reviews.llvm.org/D142864 |
Co-authored-by: Nicole Mazzuca <mazzucan@outlook.com>
Approved by Mirror Universe Nicole
|
I'm mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed. |
Co-authored-by: Casey Carter <cartec69@gmail.com>
|
Stephan T. Lavavej (@StephanTLavavej) |
As did I. |
|
Everyone's joining the commit party! (I pushed tiny comment changes and removed parameter names for the defaulted function.) |
|
Thanks for minimizing bugs while maximizing performance! 📉 😸 📈 |
The fix for microsoft#2900 in microsoft#3366 did not take advantage of the fact that the minimum and maximum elements of a range are always distinct except when the range has only one element. It couldn't easily do so due to the way `ranges::minmax` and `ranges::minmax_element` share the common backend `ranges::_Minmax_element_unchecked`. This PR introduces a new backend for `ranges::minmax` (`ranges::_Minmax_fn::_Minmax_fwd_unchecked`) and makes `ranges::_Minmax_element_unchecked` the private member `ranges::_Minmax_element_fn::_Minmax_element_fwd_unchecked`. Since the two are distinct, `_Minmax_fwd_unchecked` can deal in values instead of iterators, and we can unroll the first loop iteration to detect the single-element case naturally. Since no additional branch is needed, we can enable the fix for microsoft#2900 unconditionally. This refactoring is also probably a minor throughput and perf improvement, since `minmax` no longer needs to instantiate the "old" backend's return type and the new backend is tail-called. Drive-by: Fully qualify the names of ugly functions called by `ranges::minmax` and `ranges::minmax_element`.
The fix for microsoft#2900 in microsoft#3366 did not take advantage of the fact that the minimum and maximum elements of a range are always distinct except when the range has only one element. It couldn't easily do so due to the way `ranges::minmax` and `ranges::minmax_element` share the common backend `ranges::_Minmax_element_unchecked`. This PR introduces a new backend for `ranges::minmax` (`ranges::_Minmax_fn::_Minmax_fwd_unchecked`) and makes `ranges::_Minmax_element_unchecked` the private member `ranges::_Minmax_element_fn::_Minmax_element_fwd_unchecked`. Since the two are distinct, `_Minmax_fwd_unchecked` can deal in values instead of iterators, and we can unroll the first loop iteration to detect the single-element case naturally. Since no additional branch is needed, we can enable the fix for microsoft#2900 unconditionally. Drive-by: Fully qualify the names of ugly functions called by `ranges::minmax` and `ranges::minmax_element`.
Fixes #2900
After #2958 the original repro works, but the issue still exists.
I also found that if we have only one element we also have the issue.