std::experimental::ranges::copy,std::experimental::ranges::copy_if(3)

NAME
std::experimental::ranges::copy,std::experimental::ranges::copy_if - std::experimental::ranges::copy,std::experimental::ranges::copy_if

Synopsis
   Defined in header <experimental/ranges/algorithm>
   template< InputIterator I, Sentinel<I> S, WeaklyIncrementable O >
       requires IndirectlyCopyable<I, O> (1) (ranges TS)
   ranges::tagged_pair<tag::in(I), tag::out(O)>
       copy( I first, S last, O result );
   template< InputRange R, WeaklyIncrementable O >
       requires IndirectlyCopyable<ranges::iterator_t<R>, O>
   ranges::tagged_pair<tag::in(ranges::safe_iterator_t<R>), (2) (ranges TS)
   tag::out(O)>
       copy( R&& r, O result );
   template< InputIterator I, Sentinel<I> S, WeaklyIncrementable O,
             class Proj = ranges::identity,
             IndirectUnaryPredicate<projected<I, Proj>> Pred >
       requires IndirectlyCopyable<I, O> (3) (ranges TS)
   ranges::tagged_pair<tag::in(I), tag::out(O)>
       copy_if( I first, S last, O result, Pred pred, Proj proj =
   Proj{} );
   template< InputRange R, WeaklyIncrementable O,
             class Proj = ranges::identity,
             IndirectUnaryPredicate<projected<ranges::iterator_t<R>,
   Proj>> Pred > (4) (ranges TS)
       requires IndirectlyCopyable<iterator_t<R>, O>
   ranges::tagged_pair<tag::in(ranges::safe_iterator_t<R>),
   tag::out(O)>
       copy_if( R&& r, O result, Pred pred, Proj proj = Proj{} );
   Copies elements in the source range ([first, last) or r) 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 r as the source range, as if by
   ranges::copy(ranges::begin(r), ranges::end(r), 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 r as the source range, as if by
   ranges::copy_if(ranges::begin(r), ranges::end(r), result, pred, proj); except that
   result, pred and proj may not be copied.
   Notwithstanding the declarations depicted above, the actual number and order of
   template parameters for algorithm declarations is unspecified. Thus, if explicit
   template arguments are used when calling an algorithm, the program is probably
   non-portable.

Parameters
   first, last - the range of elements to copy
   r - 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(r) assignments.
   3) Exactly ranges::distance(first, last) applications of the corresponding
   projection and predicate.
   4) Exactly ranges::distance(r) applications of the corresponding projection and
   predicate.

Possible implementations

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

Second version
   template<InputRange R, WeaklyIncrementable O>
       requires IndirectlyCopyable<ranges::iterator_t<R>, O>()
   ranges::tagged_pair<tag::in(ranges::safe_iterator_t<R>), tag::out(O)>
       copy(R&& r, O result)
   {
      return ranges::copy(ranges::begin(r), ranges::end(r), result);
   }
                        Third version
   template<InputIterator I, Sentinel<I> S, WeaklyIncrementable O,
            class Proj = ranges::identity,
            IndirectUnaryPredicate<projected<I, Proj>> Pred>
       requires IndirectlyCopyable<I, O>()
   ranges::tagged_pair<tag::in(I), 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<InputRange R, WeaklyIncrementable O,
            class Proj = ranges::identity,
            IndirectUnaryPredicate<projected<ranges::iterator_t<R>, Proj>> Pred>
       requires IndirectlyCopyable<ranges::iterator_t<R>, O>()
   ranges::tagged_pair<tag::in(ranges::safe_iterator_t<R>), tag::out(O)>
       copy_if(R&& r, O result, Pred pred, Proj proj = Proj{})
   {
       return ranges::copy_if(ranges::begin(r), ranges::end(r), 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 <experimental/ranges/iterator>
 #include <iostream>
 #include <numeric>
 #include <vector>
 int main()
 {
     // see https://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 copies a range of elements to a new location
   copy_if (function template)
   (C++11)
   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 copies a range of elements omitting those that satisfy specific
   remove_copy_if criteria
                  (function template)