No C ++ 20, o <algorithm>
cabeçalho ganha dois novos algoritmos: shift_left()
eshift_right()
. Ambos aceitam qualquer LegacyForwardIterator. Para shift_left()
, é especificado que "os movimentos são executados em ordem crescente de i
partida de 0
"; para shift_right()
, é especificado que "se ForwardIt
atender aos requisitos LegacyBidirectionalIterator, as movimentações serão executadas em ordem decrescente a i
partir de last - first - n - 1
".
Posso pensar em uma maneira razoavelmente fácil de implementar 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
atender aos requisitos do LegacyBidirectionalIterator, posso ver que isso shift_right()
pode ser implementado de uma maneira muito semelhante à shift_left()
. No entanto, não está claro como se pode implementar shift_right()
para iteradores de encaminhamento não bidirecionais.
Eu descobri um algoritmo que usa o espaço [first, first+n)
como espaço de rascunho para a troca de elementos, mas parece um pouco mais inútil do que o algoritmo shift_left()
acima:
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;
}
Haveria uma maneira melhor ou "pretendida" de implementar shift_right()
?
std::move
vez destd::copy
...