У C ++ 20 <algorithm>
заголовок отримує два нові алгоритми: shift_left()
іshift_right()
. Вони обидва приймають будь-якого LegacyForwardIterator. Бо shift_left()
визначено, що "ходи виконуються у порядку зростання, i
починаючи з 0
"; для shift_right()
, зазначено, що "якщо ForwardIt
відповідає вимогам LegacyBidirectionalIterator, то переміщення виконуються у порядку зменшення, i
починаючи з last - first - n - 1
".
Я можу придумати досить простий спосіб втілення shift_left()
:
template <typename ForwardIt>
constexpr inline ForwardIt shift_left(ForwardIt first, ForwardIt last, typename std::iterator_traits<ForwardIt>::difference_type n) {
if (n <= 0) return last;
ForwardIt it = first;
for (; n > 0; --n, ++it) {
if (it == last) return first;
}
return std::move(it, last, first);
}
Якщо ForwardIt
відповідає вимогам LegacyBidirectionalIterator, я можу побачити, що це shift_right()
може бути реалізовано дуже схожим чином shift_left()
. Однак зовсім не зрозуміло, як можна реалізувати shift_right()
для ненаправлених ітераторів переадресації.
Я розібрався з алгоритмом, який використовує простір в [first, first+n)
якості місця для подряпин для заміни елементів, але він здається трохи більш марним, ніж алгоритм для shift_left()
вище:
template <typename ForwardIt>
constexpr inline ForwardIt shift_right(ForwardIt first, ForwardIt last, typename std::iterator_traits<ForwardIt>::difference_type n) {
if (n <= 0) return first;
ForwardIt it = first;
for (; n > 0; --n, ++it) {
if (it == last) return last;
}
ForwardIt ret = it;
ForwardIt ret_it = first;
for (; it != last; ++it) {
std::iter_swap(ret_it, it);
ret_it++;
if (ret_it == ret) ret_it = first;
}
return ret;
}
Чи був би кращий або «призначений» спосіб реалізації shift_right()
?
std::move
замістьstd::copy
...