Spec-Zone.ru › C++

std::ranges::copy, std::ranges::copy_if, std::ranges::copy_result, std::ranges::copy_if_result

Определено в заголовочном файле <algorithm>
Сигнатура вызова
template< std::input_iterator I, std::sentinel_for<I> S,
          std::weakly_incrementable O >
    requires std::indirectly_copyable<I, O>
constexpr copy_result<I, O>
    copy( I first, S last, O d_first );
(1) (начиная с C++20)
template< ranges::input_range R, std::weakly_incrementable O >
    requires std::indirectly_copyable<ranges::iterator_t<R>, O>
constexpr copy_result<ranges::borrowed_iterator_t<R>, O>
    copy( R&& r, O d_first );
(2) (начиная с C++20)
template< std::input_iterator I, std::sentinel_for<I> S,
          std::weakly_incrementable O, class Proj = std::identity,
          std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
    requires std::indirectly_copyable<I, O>
constexpr copy_if_result<I, O>
    copy_if( I first, S last, O d_first, Pred pred, Proj proj = {} );
(3) (начиная с C++20)
template< ranges::input_range R,
          std::weakly_incrementable O, class Proj = std::identity,
          std::indirect_unary_predicate
              <std::projected<ranges::iterator_t<R>, Proj>> Pred >
    requires std::indirectly_copyable<ranges::iterator_t<R>, O>
constexpr copy_if_result<ranges::borrowed_iterator_t<R>, O>
    copy_if( R&& r, O d_first, Pred pred, Proj proj = {} );
(4) (начиная с C++20)
template< /*execution-policy*/ Ep,
          std::random_access_iterator I, std::sized_sentinel_for<I> S,
          std::random_access_iterator O, std::sized_sentinel_for<O> OutS >
    requires std::indirectly_copyable<I, O>
copy_result<I, O>
    copy( Ep&& policy, I first, S last, O d_first, OutS d_last );
(5) (начиная с C++26)
template< /*execution-policy*/ Ep,
          /*sized-random-access-range*/ R,
          /*sized-random-access-range*/ OutR >
    requires std::indirectly_copyable<ranges::iterator_t<R>,
                                      ranges::iterator_t<OutR>>
copy_result<ranges::borrowed_iterator_t<R>,
            ranges::borrowed_iterator_t<OutR>>
    copy( Ep&& policy, R&& r, OutR&& d_r );
(6) (начиная с C++26)
template< /*execution-policy*/ Ep,
          std::random_access_iterator I, std::sized_sentinel_for<I> S,
          std::random_access_iterator O, std::sized_sentinel_for<O> OutS,
          class Proj = std::identity,
          std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
    requires std::indirectly_copyable<I, O>
copy_if_result<I, O>
    copy_if( Ep&& policy, I first, S last, O d_first, OutS d_last,
             Pred pred, Proj proj = {} );
(7) (начиная с C++26)
template< /*execution-policy*/ Ep,
          /*sized-random-access-range*/ R,
          /*sized-random-access-range*/ OutR,
          class Proj = std::identity,
          std::indirect_unary_predicate
              <std::projected<ranges::iterator_t<R>, Proj>> Pred >
    requires std::indirectly_copyable<ranges::iterator_t<R>,
                                      ranges::iterator_t<OutR>>
copy_if_result<ranges::borrowed_iterator_t<R>,
               ranges::borrowed_iterator_t<OutR>>
    copy_if( Ep&& policy, R&& r, OutR&& d_r,
             Pred pred, Proj proj = {} );
(8) (начиная с C++26)
Вспомогательные типы
template< class I, class O >
using copy_result = ranges::in_out_result<I, O>;
(9) (начиная с C++20)
template< class I, class O >
using copy_if_result = ranges::in_out_result<I, O>;
(10) (начиная с C++20)

Определение /*execution-policy*/ см. на этой странице; определение /*sized-random-access-range*/ см. на этой странице.

Копирует элементы исходного диапазона [first, last) или r в целевой диапазон.

1,2) copy копирует все элементы исходного диапазона, начиная с начала и продвигаясь к концу. Целевой диапазон начинается с d_first.
Если d_first находится в исходном диапазоне, поведение не определено.
3,4) copy_if копирует только те элементы (преобразованные с помощью proj), для которых предикат pred возвращает true. Целевой диапазон начинается с d_first.
Если исходный и целевой диапазоны перекрываются, поведение не определено.
5-8) То же, что и (1-4), но порядок копирования определяется policy. Если целевой диапазон исчерпан до достижения конца исходного диапазона, оставшиеся элементы исходного диапазона не копируются.
Если исходный и целевой диапазоны перекрываются, поведение не определено.
5,7) Целевой диапазон — это [d_first, d_last).
6,8) Целевой диапазон — это d_r.

Описанные на этой странице объекты, подобные функциям, являются функциональными объектами алгоритмов (неформально известными как niebloids), то есть:

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

Параметры

first, last - пара итератора и сентинела, задающая исходный диапазон
r - исходный диапазон
d_first - начало целевого диапазона
d_last - сентинел целевого диапазона
d_r - целевой диапазон
pred - предикат, применяемый к (преобразованным) элементам
proj - проекция, применяемая к элементам исходного диапазона
policy - используемая политика выполнения

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

Объект ranges::copy_result или ranges::copy_if_result, в котором:

  • Поле данных in содержит итератор, следующий за последним скопированным элементом исходного диапазона, или итератор на начало исходного диапазона, если ни один элемент не скопирован.
  • Поле данных out содержит итератор, следующий за последним элементом целевого диапазона, в который было выполнено копирующее присваивание, или итератор на начало целевого диапазона, если ни один элемент не скопирован.

Сложность

Пусть

  • \(\scriptsize N_1\)N1 равно ranges::distance(first, last) или ranges::distance(r), а
  • \(\scriptsize N_2\)N2 равно ranges::distance(d_first, d_last) или ranges::distance(d_r):
1,2) Ровно \(\scriptsize N_1\)N1 операций присваивания.
3,4) Ровно \(\scriptsize N_1\)N1 pred и proj, а также не более \(\scriptsize N_1\)N1 операций присваивания.
5,6) Ровно \(\scriptsize \min(N_1,N_2)\)min(N1,N2) операций присваивания.
7,8) Ровно \(\scriptsize \min(N_1,N_2)\)min(N1,N2) pred и proj, а также не более \(\scriptsize \min(N_1,N_2)\)min(N1,N2) операций присваивания.

Исключения

5-8) Во время выполнения:
  • Если временные ресурсы памяти, необходимые для параллелизации, недоступны, выбрасывается std::bad_alloc.
  • Если при доступе к объектам через аргумент алгоритма выбрасывается необработанное исключение, поведение определяется политикой выполнения (для стандартных политик вызывается std::terminate).

Примечания

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

При копировании перекрывающихся диапазонов ranges::copy подходит для копирования влево (начало целевого диапазона находится за пределами исходного диапазона), тогда как ranges::copy_backward подходит для копирования вправо (конец целевого диапазона находится за пределами исходного диапазона).

ranges::copy_if является стабильным алгоритмом. Относительный порядок копируемых элементов сохраняется.

Для перегрузок параллельных алгоритмов возможны дополнительные затраты производительности, если std::iter_value_t<I> или ranges::range_value_t<R> не удовлетворяет требованиям концепта move_constructible.

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

copy
struct copy_fn
{
    template<std::input_iterator I, std::sentinel_for<I> S, std::weakly_incrementable O>
        requires std::indirectly_copyable<I, O>
    constexpr ranges::copy_result<I, O> operator()(I first, S last, O d_first) const
    {
        for (; first != last; ++first, (void)++d_first)
            *d_first = *first;
        return {std::move(first), std::move(d_first)};
    }
    
    template<ranges::input_range R, std::weakly_incrementable O>
        requires std::indirectly_copyable<ranges::iterator_t<R>, O>
    constexpr ranges::copy_result<ranges::borrowed_iterator_t<R>, O>
        operator()(R&& r, O d_first) const
    {
        return (*this)(ranges::begin(r), ranges::end(r), std::move(d_first));
    }
    
    template<ranges::forward_range R, std::weakly_incrementable O>
        requires std::indirectly_copyable<ranges::iterator_t<R>, O>
    constexpr ranges::copy_result<ranges::borrowed_iterator_t<R>, O>
        operator()(R&& r, O d_first) const
    {
        return (*this)(ranges::begin(r),
                       ranges::next(ranges::begin(r), ranges::end(r)),
                       std::move(d_first));
    }
};

inline constexpr copy_fn copy;
copy_if
struct copy_if_fn
{
    template<std::input_iterator I, std::sentinel_for<I> S, std::weakly_incrementable O,
             class Proj = std::identity,
             std::indirect_unary_predicate<std::projected<I, Proj>> Pred>
        requires std::indirectly_copyable<I, O>
    constexpr ranges::copy_if_result<I, O>
        operator()(I first, S last, O d_first, Pred pred, Proj proj = {}) const
    {
        for (; first != last; ++first)
            if (std::invoke(pred, std::invoke(proj, *first)))
            {
                *d_first = *first;
                ++d_first;
            }
        return {std::move(first), std::move(d_first)};
    }
    
    template<ranges::input_range R, std::weakly_incrementable O,
             class Proj = std::identity,
             std::indirect_unary_predicate
                 <std::projected<ranges::iterator_t<R>, Proj>> Pred>
        requires std::indirectly_copyable<ranges::iterator_t<R>, O>
    constexpr ranges::copy_if_result<ranges::borrowed_iterator_t<R>, O>
        operator()(R&& r, O d_first, Pred pred, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r),
                       std::move(d_first), std::ref(pred), std::ref(proj));
    }
    
    template<ranges::forward_range R, std::weakly_incrementable O,
             class Proj = std::identity,
             std::indirect_unary_predicate
                 <std::projected<ranges::iterator_t<R>, Proj>> Pred>
        requires std::indirectly_copyable<ranges::iterator_t<R>, O>
    constexpr ranges::copy_if_result<ranges::borrowed_iterator_t<R>, O>
        operator()(R&& r, O d_first, Pred pred, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r),
                       ranges::next(ranges::begin(r), ranges::end(r)),
                       std::move(d_first), std::ref(pred), std::ref(proj));
    }
};

inline constexpr copy_if_fn copy_if;

Пример

В следующем коде ranges::copy используется как для копирования содержимого одного std::vector в другой, так и для вывода полученного std::vector.

#include <algorithm>
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>

int main()
{
    std::vector<int> source(10);
    std::iota(source.begin(), source.end(), 0);
    std::vector<int> destination;
    std::ranges::copy(source.begin(), source.end(), std::back_inserter(destination));
    
// or, alternatively,
//  std::vector<int> destination(source.size());
//  std::ranges::copy(source.begin(), source.end(), destination.begin());
// either way is equivalent to
//  std::vector<int> destination = source;
    
    std::cout << "Destination contains: ";
    std::ranges::copy(destination, std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
    
    std::cout << "Odd numbers in destination are: ";
    std::ranges::copy_if(destination, std::ostream_iterator<int>(std::cout, " "),
                         [](int x) { return (x % 2) == 1; });
    std::cout << '\n';
}

Вывод:

Destination contains: 0 1 2 3 4 5 6 7 8 9
Odd numbers in destination are: 1 3 5 7 9

См. также

copycopy_if
(C++11)
копирует диапазон элементов в новое место
(шаблон функции)
ranges::copy_backward
(C++20)
копирует диапазон элементов в обратном порядке
(функциональный объект алгоритма)
ranges::reverse_copy
(C++20)
создаёт копию диапазона в обратном порядке
(функциональный объект алгоритма)
ranges::copy_n
(C++20)
копирует заданное число элементов в новое место
(функциональный объект алгоритма)
ranges::fill
(C++20)
присваивает элементам диапазона заданное значение
(функциональный объект алгоритма)
ranges::remove_copyranges::remove_copy_if
(C++20)(C++20)
копирует диапазон элементов, исключая те, которые соответствуют заданным критериям
(функциональный объект алгоритма)

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

Spec-Zone.ru

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