[libc++] Implement ranges::copy{, _n, _if, _backward}

Reviewed By: Mordante, var-const, #libc

Spies: sstefan1, libcxx-commits, mgorny

Differential Revision: https://reviews.llvm.org/D122982

NOKEYCHECK=True
GitOrigin-RevId: 1d83750f631d60bf6f371fa3fd0efc0499470d3f
diff --git a/include/algorithm b/include/algorithm
index 919c7cc..9feb59b 100644
--- a/include/algorithm
+++ b/include/algorithm
@@ -191,6 +191,53 @@
            indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less>
     constexpr ranges::minmax_element_result<borrowed_iterator_t<R>>
       minmax_element(R&& r, Comp comp = {}, Proj proj = {});                              // since C++20
+
+  template<class I, class O>
+      using copy_result = in_out_result<I, O>;                                              // since C++20
+
+    template<class I, class O>
+      using copy_n_result = in_out_result<I, O>;                                            // since C++20
+
+  template<class I, class O>
+    using copy_if_result = in_out_result<I, O>;                                             // since C++20
+
+  template<class I1, class I2>
+    using copy_backward_result = in_out_result<I1, I2>;                                     // since C++20
+
+  template<input_iterator I, sentinel_for<I> S, weakly_incrementable O>
+    requires indirectly_copyable<I, O>
+    constexpr ranges::copy_result<I, O> ranges::copy(I first, S last, O result);            // since C++20
+
+  template<input_range R, weakly_incrementable O>
+    requires indirectly_copyable<iterator_t<R>, O>
+    constexpr ranges::copy_result<borrowed_iterator_t<R>, O> ranges::copy(R&& r, O result); // since C++20
+
+  template<input_iterator I, weakly_incrementable O>
+    requires indirectly_copyable<I, O>
+    constexpr ranges::copy_n_result<I, O>
+      ranges::copy_n(I first, iter_difference_t<I> n, O result);                            // since C++20
+
+  template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Proj = identity,
+           indirect_unary_predicate<projected<I, Proj>> Pred>
+    requires indirectly_copyable<I, O>
+    constexpr ranges::copy_if_result<I, O>
+      ranges::copy_if(I first, S last, O result, Pred pred, Proj proj = {});                // since C++20
+
+  template<input_range R, weakly_incrementable O, class Proj = identity,
+           indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred>
+    requires indirectly_copyable<iterator_t<R>, O>
+    constexpr ranges::copy_if_result<borrowed_iterator_t<R>, O>
+      ranges::copy_if(R&& r, O result, Pred pred, Proj proj = {});                          // since C++20
+
+  template<bidirectional_iterator I1, sentinel_for<I1> S1, bidirectional_iterator I2>
+    requires indirectly_copyable<I1, I2>
+    constexpr ranges::copy_backward_result<I1, I2>
+      ranges::copy_backward(I1 first, S1 last, I2 result);                                  // since C++20
+
+  template<bidirectional_range R, bidirectional_iterator I>
+    requires indirectly_copyable<iterator_t<R>, I>
+    constexpr ranges::copy_backward_result<borrowed_iterator_t<R>, I>
+      ranges::copy_backward(R&& r, I result);                                               // since C++20
 }
 
     constexpr bool     // constexpr in C++20
@@ -908,6 +955,10 @@
 #include <__algorithm/pop_heap.h>
 #include <__algorithm/prev_permutation.h>
 #include <__algorithm/push_heap.h>
+#include <__algorithm/ranges_copy.h>
+#include <__algorithm/ranges_copy_backward.h>
+#include <__algorithm/ranges_copy_if.h>
+#include <__algorithm/ranges_copy_n.h>
 #include <__algorithm/ranges_count.h>
 #include <__algorithm/ranges_count_if.h>
 #include <__algorithm/ranges_find.h>