Spec-Zone.ru › C++

std::ranges::rotate_copy, std::ranges::rotate_copy_result

Определено в заголовочном файле <algorithm>
Подпись вызова
template< std::forward_iterator I, std::sentinel_for<I> S,
          std::weakly_incrementable O >
requires std::indirectly_copyable<I, O>
constexpr rotate_copy_result<I, O>
    rotate_copy( I first, I middle, S last, O result );
(1) (с C++20)
template< ranges::forward_range R, std::weakly_incrementable O >
requires std::indirectly_copyable<ranges::iterator_t<R>, O>
constexpr rotate_copy_result<ranges::borrowed_iterator_t<R>, O>
    rotate_copy( R&& r, ranges::iterator_t<R> middle, O result );
(2) (с C++20)
Вспомогательные типы
template< class I, class O >
using rotate_copy_result = in_out_result<I, O>;
(3) (с C++20)
1) Копирует элементы из диапазона-источника [first, last), в диапазон-приемник, начиная с result таким образом, что элемент *middle становится первым элементом диапазона-приемника, а *(middle - 1) — последним. В результате, диапазон-приемник содержит *циклический сдвиг влево* копию диапазона-источника.
Поведение не определено, если ни [first, middle) ни [middle, last) не являются корректным диапазоном, или диапазоны-источник и-приемник перекрываются.
2) То же, что и (1), но использует r в качестве диапазона-источника, как будто используя ranges::begin(r) в качестве first и ranges::end(r) в качестве last.

Функциональные сущности, описанные на этой странице, являются *неблокирующими* (niebloids), то есть:

  • Явные списки шаблонных аргументов не могут быть указаны при вызове любой из них.
  • Ни одна из них не видна для поиска зависимого от аргументов.
  • Когда любая из них находится с помощью обычного поиска без квалификатора в качестве имени слева от оператора вызова функции, поиск зависимого от аргументов запрещается.

На практике они могут быть реализованы как объекты функций или с помощью специальных расширений компилятора.

Параметры

first, last - диапазон-источник элементов, которые нужно скопировать
r - диапазон-источник элементов, которые нужно скопировать
middle - итератор на элемент, который должен появиться в начале диапазона-приемника
result - начало диапазона-приемника

Возвращаемое значение

{last, result + N}, где N = ranges::distance(first, last).

Сложность

Линейная: ровно N присваиваний.

Примечания

Если тип значения является TriviallyCopyable, и типы итераторов удовлетворяют contiguous_iterator, реализации ranges::rotate_copy обычно избегают множественных присваиваний, используя функцию «массовой копии», такую как std::memmove.

Возможная реализация

См. также реализации в libstdc++ и MSVC STL.

struct rotate_copy_fn
{
    template<std::forward_iterator I, std::sentinel_for<I> S, std::weakly_incrementable O>
    requires std::indirectly_copyable<I, O>
    constexpr ranges::rotate_copy_result<I, O>
        operator()(I first, I middle, S last, O result) const
    {
        auto c1 {ranges::copy(middle, std::move(last), std::move(result))};
        auto c2 {ranges::copy(std::move(first), std::move(middle), std::move(c1.out))};
        return {std::move(c1.in), std::move(c2.out)};
    }
 
    template<ranges::forward_range R, std::weakly_incrementable O>
    requires std::indirectly_copyable<ranges::iterator_t<R>, O>
    constexpr ranges::rotate_copy_result<ranges::borrowed_iterator_t<R>, O>
        operator()(R&& r, ranges::iterator_t<R> middle, O result) const
    {
        return (*this)(ranges::begin(r), std::move(middle),
                       ranges::end(r), std::move(result));
    }
};
 
inline constexpr rotate_copy_fn rotate_copy {};

Пример

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
 
int main()
{
    std::vector<int> src {1, 2, 3, 4, 5};
    std::vector<int> dest(src.size());
    auto pivot = std::ranges::find(src, 3);
 
    std::ranges::rotate_copy(src, pivot, dest.begin());
    for (int i : dest)
        std::cout << i << ' ';
    std::cout << '\n';
 
    // copy the rotation result directly to the std::cout
    pivot = std::ranges::find(dest, 1);
    std::ranges::rotate_copy(dest, pivot, std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
}

Вывод:

3 4 5 1 2
1 2 3 4 5

См. также

ranges::rotate
(C++20)
циклически сдвигает порядок элементов в диапазоне
(неблокирующая функция)
ranges::copyranges::copy_if
(C++20)(C++20)
копирует диапазон элементов в новое местоположение
(неблокирующая функция)
rotate_copy
копирует и циклически сдвигает диапазон элементов
(шаблонная функция)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/algorithm/ranges/rotate_copy

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API