In C ++ 20, l' <algorithm>
intestazione ottiene due nuovi algoritmi: shift_left()
eshift_right()
. Entrambi accettano qualsiasi LegacyForwardIterator. Per shift_left()
, si specifica che "le mosse vengono eseguite in ordine crescente a i
partire da 0
"; per shift_right()
, si specifica che "se ForwardIt
soddisfa i requisiti LegacyBidirectionalIterator, le mosse vengono eseguite in ordine decrescente a i
partire da last - first - n - 1
".
Mi viene in mente un modo ragionevolmente semplice per implementare 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);
}
Se ForwardIt
soddisfa i requisiti LegacyBidirectionalIterator, posso vedere che shift_right()
può essere implementato in modo molto simile a shift_left()
. Tuttavia, non è affatto chiaro come si possa implementare shift_right()
per iteratori forward non bidirezionali.
Ho capito un algoritmo che utilizza lo spazio [first, first+n)
come spazio di lavoro per lo scambio di elementi, ma sembra un po 'più dispendioso dell'algoritmo di cui shift_left()
sopra:
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;
}
Esisterebbe un modo migliore o "previsto" di attuare shift_right()
?
std::move
invece distd::copy
...