У 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...