[libcxx-commits] [libcxx] [libc++][ranges] implement `ranges::shift_left` (PR #83231)
Xiaoyang Liu via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Mar 4 23:01:53 PST 2024
xiaoyang-sde wrote:
I attempt to explain how the `__shift_left` function works in this comment. The idea is to perform operations with linear complexity on the range at most twice – first when finding `__m` and then when actually moving the elements. Overall, all execution-flow involves at most two linear operations on the range.
```cpp
template <class _AlgPolicy, class _Iter, class _Sent>
_LIBCPP_HIDE_FROM_ABI constexpr pair<_Iter, _Iter>
__shift_left(_Iter __first, _Sent __last, typename _IterOps<_AlgPolicy>::template __difference_type<_Iter> __n) {
_LIBCPP_ASSERT_UNCATEGORIZED(__n >= 0, "__n must be greater than or equal to 0");
if (__n == 0) {
_Iter __end = _IterOps<_AlgPolicy>::next(__first, __last); // This operation is either constant or linear
return {std::move(__first), std::move(__end)};
}
_Iter __m = __first;
if constexpr (sized_sentinel_for<_Sent, _Iter>) {
auto __size = _IterOps<_AlgPolicy>::distance(__first, __last); // This operation is constant
if (__n >= __size) {
return {std::move(__first), std::move(__first)};
}
_IterOps<_AlgPolicy>::advance(__m, __n); // This operation is either constant or linear
} else {
// This for-loop is linear
for (; __n > 0; --__n) {
if (__m == __last) {
return {std::move(__first), std::move(__first)};
}
++__m;
}
}
_Iter __result = std::__move<_AlgPolicy>(__m, __last, __first).second; // This operation is linear
return {std::move(__first), std::move(__result)};
}
```
https://github.com/llvm/llvm-project/pull/83231
More information about the libcxx-commits
mailing list