Trong C ++ 20, <algorithm>
tiêu đề đạt được hai thuật toán mới: shift_left()
vàshift_right()
. Cả hai đều chấp nhận bất kỳ LegacyForwardIterator. Đối với shift_left()
, nó được chỉ định rằng "các động tác được thực hiện theo thứ tự tăng dần i
bắt đầu từ 0
"; cho shift_right()
, nó được chỉ định rằng "nếu ForwardIt
đáp ứng các yêu cầu LegacyBidirectionalIterator, thì các bước di chuyển được thực hiện theo thứ tự giảm dần i
bắt đầu từ last - first - n - 1
".
Tôi có thể nghĩ ra một cách hợp lý dễ thực hiện 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);
}
Nếu ForwardIt
đáp ứng các yêu cầu của LegacyBidirectionalIterator, tôi có thể thấy điều đó shift_right()
có thể được thực hiện theo cách rất giống như shift_left()
. Tuy nhiên, không rõ ràng về cách người ta có thể thực hiện shift_right()
cho các trình vòng lặp chuyển tiếp không hai chiều.
Tôi đã tìm ra một thuật toán sử dụng không gian ở [first, first+n)
dạng không gian đầu để hoán đổi các phần tử, nhưng có vẻ lãng phí hơn một chút so với thuật toán shift_left()
ở trên:
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;
}
Sẽ có một cách tốt hơn hoặc "dự định" để thực hiện shift_right()
?
std::move
thay vìstd::copy
...