En C ++ 20, l'en- <algorithm>
tête gagne deux nouveaux algorithmes: shift_left()
etshift_right()
. Les deux acceptent n'importe quel LegacyForwardIterator. Pour shift_left()
, il est précisé que "les déplacements sont effectués dans un ordre croissant de i
départ 0
"; car shift_right()
, il est spécifié que "s'il ForwardIt
répond aux exigences LegacyBidirectionalIterator, alors les déplacements sont effectués dans un ordre décroissant à i
partir de last - first - n - 1
".
Je peux penser à un moyen raisonnablement facile à mettre en œuvre 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);
}
Si ForwardIt
répond aux exigences LegacyBidirectionalIterator, je peux voir que cela shift_right()
peut être implémenté d'une manière très similaire à shift_left()
. Cependant, il n'est pas du tout clair comment on pourrait implémenter shift_right()
des itérateurs de transfert non bidirectionnels.
J'ai trouvé un algorithme qui utilise l'espace à [first, first+n)
comme espace de travail pour échanger des éléments, mais il semble un peu plus inutile que l'algorithme shift_left()
ci-dessus:
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;
}
Existe-t-il une manière de mise en œuvre meilleure ou "prévue" shift_right()
?
std::move
au lieu destd::copy
...