# std::experimental::ranges::copy, std::experimental::ranges::copy_if

From cppreference.com
< cpp‎ | experimental‎ | ranges

Defined in header `<experimental/ranges/algorithm>` |  |
template < ranges::InputIterator I, ranges::Sentinel<I> S, ranges::WeaklyIncrementable O > requires ranges::IndirectlyCopyable<I, O>() ranges::tagged_pair<ranges::tag::in(I), ranges::tag::out(O)> copy(I first, S last, O result); | (1) | (ranges TS)
template < ranges::InputRange Rng, ranges::WeaklyIncrementable O > requires ranges::IndirectlyCopyable<ranges::iterator_t<Rng>, O>() ranges::tagged_pair<ranges::tag::in(ranges::safe_iterator_t<Rng>), ranges::tag::out(O)> copy(Rng&& rng, O result); | (2) | (ranges TS)
template < ranges::InputIterator I, ranges::Sentinel<I> S, ranges::WeaklyIncrementable O, class Proj = ranges::identity, ranges::IndirectPredicate<ranges::projected<I, Proj>> Pred > requires ranges::IndirectlyCopyable<I, O>() ranges::tagged_pair<ranges::tag::in(I), ranges::tag::out(O)> copy_if(I first, S last, O result, Pred pred, Proj proj = Proj{}); | (3) | (ranges TS)

template < ranges::InputRange Rng, ranges::WeaklyIncrementable O,

class Proj = ranges::identity,
ranges::IndirectPredicate<ranges::projected<ranges::iterator_t<Rng>, Proj>> Pred >
requires ranges::IndirectlyCopyable<iterator_t<Rng>, O>()
ranges::tagged_pair<ranges::tag::in(ranges::safe_iterator_t<Rng>), ranges::tag::out(O)>

copy_if(Rng&& rng, O result, Pred pred, Proj proj = Proj{});

(4)

(ranges TS)

Copies elements in the source range (`[first,last)` or `rng`) into the destination range beginning at `result`, starting from the first element in the source range and proceeding to the last one.

1) Copies all elements in the range `[first, last)`. For each non-negative integer `n < (last - first)`, performs *(result + n) = *(first + n). The behavior is undefined if `result` is within the range `[first, last)`. In this case, ranges::copy_backward may be used instead.
2) Same as (1), but uses `rng` as the source range, as if by ranges::copy(ranges::begin(rng), ranges::end(rng), result); except that `result` may not be copied.
3) Only copies the elements for which the predicate `pred` returns true when applied to the element's value as projected by the projection `proj`. The order of the elements that are copied is preserved. The behavior is undefined if the source and the destination ranges overlap.
4) Same as (3), but uses `rng` as the source range, as if by ranges::copy_if(ranges::begin(rng), ranges::end(rng), result, pred, proj); except that `result`, `pred` and `proj` may not be copied.

### Parameters

first, last | - | the range of elements to copy
rng | - | the range of elements to copy
result | - | the beginning of the destination range
pred | - | predicate to apply to the projected elements
proj | - | projection to apply to the elements

### Return value

A `tagged_pair` object containing the following two members:

- The first member, with the tag `tag::in`, is the past-the-end iterator of the source range (that is, an iterator of type `I` that compares equal to the sentinel`last`).
- The second member, with the tag `tag::out`, is the past-the-end iterator of the result range.

### Complexity

1) Exactly ranges::distance(first, last) assignments.
2) Exactly ranges::distance(rng) assignments.
3) Exactly ranges::distance(first, last) applications of the corresponding projection and predicate.
3) Exactly ranges::distance(rng) applications of the corresponding projection and predicate.

### Possible implementations

First version

    template <ranges::InputIterator I, ranges::Sentinel<I> S, ranges::WeaklyIncrementable O>
      requires ranges::IndirectlyCopyable<I, O>()
    ranges::tagged_pair<ranges::tag::in(I), ranges::tag::out(O)>
      copy(I first, S last, O result)
    {
        for (; first != last; ++first, (void)++result)
            *result = *first;
        return {first, result};
    }

Second version

    template <ranges::InputRange Rng, ranges::WeaklyIncrementable O>
      requires ranges::IndirectlyCopyable<ranges::iterator_t<Rng>, O>()
    ranges::tagged_pair<ranges::tag::in(ranges::safe_iterator_t<Rng>), ranges::tag::out(O)>
      copy(Rng&& rng, O result)
    {
       return ranges::copy(ranges::begin(rng), ranges::end(rng), result);
    }

Third version

    template <ranges::InputIterator I, ranges::Sentinel<I> S, ranges::WeaklyIncrementable O,
             class Proj = ranges::identity,
             ranges::IndirectPredicate<ranges::projected<I, Proj>> Pred>
      requires ranges::IndirectlyCopyable<I, O>()
    ranges::tagged_pair<ranges::tag::in(I), ranges::tag::out(O)>
      copy_if(I first, S last, O result, Pred pred, Proj proj = Proj{})
    {
        for (; first != last; ++first) {
            if (ranges::invoke(pred, ranges::invoke(proj, *first))){
                *result = *first;
                ++result;
            }
        }
        return {first, result};
    }

Fourth version

    template <ranges::InputRange Rng, ranges::WeaklyIncrementable O,
           class Proj = ranges::identity,
           ranges::IndirectPredicate<ranges::projected<ranges::iterator_t<Rng>, Proj>> Pred>
      requires ranges::IndirectlyCopyable<ranges::iterator_t<Rng>, O>()
    ranges::tagged_pair<ranges::tag::in(ranges::safe_iterator_t<Rng>), ranges::tag::out(O)>
      copy_if(Rng&& rng, O result, Pred pred, Proj proj = Proj{})
    {
       return ranges::copy_if(ranges::begin(rng), ranges::end(rng), result, pred, proj);
    }

### Example

The following code uses copy to both copy the contents of one vector to another and to display the resulting vector:

Run this code

    #include <experimental/ranges/algorithm>
    #include <iostream>
    #include <vector>
    #include <experimental/ranges/iterator>
    #include <numeric>

    int main()
    {
        // see http://en.cppreference.com/w/cpp/language/namespace_alias
        namespace ranges = std::experimental::ranges;

        std::vector<int> from_vector(10);
        std::iota(from_vector.begin(), from_vector.end(), 0);

        std::vector<int> to_vector;
        ranges::copy_if(from_vector.begin(), from_vector.end(),
                        ranges::back_inserter(to_vector),
                        [](const auto i) {
                           return i % 3;
                        });
    // or, alternatively,
    //  std::vector<int> to_vector(from_vector.size());
    //  std::copy(from_vector, to_vector.begin());

        std::cout << "to_vector contains: ";

        ranges::copy(to_vector, ranges::ostream_iterator<int>(std::cout, " "));
        std::cout << '\n';
    }

Output:

    to_vector contains: 1 2 4 5 7 8

### See also

copy copy_if (C++11) | copies a range of elements to a new location (function template)
copy_backward | copies a range of elements in backwards order (function template)
reverse_copy | creates a copy of a range that is reversed (function template)
copy_n | copies a number of elements to a new location (function template)
fill | assigns a range of elements a certain value (function template)
remove_copy remove_copy_if | copies a range of elements omitting those that satisfy specific criteria (function template)

Retrieved from "http://en.cppreference.com/mwiki/index.php?title=cpp/experimental/ranges/algorithm/copy&oldid=89910"