[libc++][ranges] Implement `construct_at` and `destroy{,_at}`.

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

NOKEYCHECK=True
GitOrigin-RevId: b9bc3c107c6cee93cd1a7004142f11741e0225bf
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index 7efe038..3070859 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -249,6 +249,7 @@
   __memory/concepts.h
   __memory/construct_at.h
   __memory/pointer_traits.h
+  __memory/ranges_construct_at.h
   __memory/ranges_uninitialized_algorithms.h
   __memory/raw_storage_iterator.h
   __memory/shared_ptr.h
diff --git a/include/__memory/construct_at.h b/include/__memory/construct_at.h
index 3b58451..580ce78 100644
--- a/include/__memory/construct_at.h
+++ b/include/__memory/construct_at.h
@@ -14,6 +14,7 @@
 #include <__debug>
 #include <__iterator/access.h>
 #include <__memory/addressof.h>
+#include <__memory/voidify.h>
 #include <__utility/forward.h>
 #include <type_traits>
 #include <utility>
@@ -31,10 +32,10 @@
 template<class _Tp, class ..._Args, class = decltype(
     ::new (declval<void*>()) _Tp(declval<_Args>()...)
 )>
-_LIBCPP_INLINE_VISIBILITY
+_LIBCPP_HIDE_FROM_ABI
 constexpr _Tp* construct_at(_Tp* __location, _Args&& ...__args) {
     _LIBCPP_ASSERT(__location, "null pointer given to construct_at");
-    return ::new ((void*)__location) _Tp(_VSTD::forward<_Args>(__args)...);
+    return ::new (_VSTD::__voidify(*__location)) _Tp(_VSTD::forward<_Args>(__args)...);
 }
 
 #endif
@@ -46,7 +47,7 @@
 
 template <class _ForwardIterator>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
-void __destroy(_ForwardIterator, _ForwardIterator);
+_ForwardIterator __destroy(_ForwardIterator, _ForwardIterator);
 
 template <class _Tp, typename enable_if<!is_array<_Tp>::value, int>::type = 0>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
@@ -66,9 +67,10 @@
 
 template <class _ForwardIterator>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
-void __destroy(_ForwardIterator __first, _ForwardIterator __last) {
+_ForwardIterator __destroy(_ForwardIterator __first, _ForwardIterator __last) {
     for (; __first != __last; ++__first)
         _VSTD::__destroy_at(_VSTD::addressof(*__first));
+    return __first;
 }
 
 #if _LIBCPP_STD_VER > 14
@@ -90,7 +92,7 @@
 template <class _ForwardIterator>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
 void destroy(_ForwardIterator __first, _ForwardIterator __last) {
-    _VSTD::__destroy(_VSTD::move(__first), _VSTD::move(__last));
+  (void)_VSTD::__destroy(_VSTD::move(__first), _VSTD::move(__last));
 }
 
 template <class _ForwardIterator, class _Size>
diff --git a/include/__memory/ranges_construct_at.h b/include/__memory/ranges_construct_at.h
new file mode 100644
index 0000000..99ae299
--- /dev/null
+++ b/include/__memory/ranges_construct_at.h
@@ -0,0 +1,144 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___MEMORY_RANGES_CONSTRUCT_AT_H
+#define _LIBCPP___MEMORY_RANGES_CONSTRUCT_AT_H
+
+#include <__concepts/destructible.h>
+#include <__config>
+#include <__function_like.h>
+#include <__iterator/incrementable_traits.h>
+#include <__iterator/readable_traits.h>
+#include <__memory/concepts.h>
+#include <__memory/construct_at.h>
+#include <__ranges/access.h>
+#include <__ranges/concepts.h>
+#include <__ranges/dangling.h>
+#include <__utility/declval.h>
+#include <__utility/forward.h>
+#include <__utility/move.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+namespace ranges {
+
+// construct_at
+
+namespace __construct_at {
+
+struct __fn final : private __function_like {
+
+  _LIBCPP_HIDE_FROM_ABI
+  constexpr explicit __fn(__tag __x) noexcept : __function_like(__x) {}
+
+  template<class _Tp, class... _Args, class = decltype(
+    ::new (declval<void*>()) _Tp(declval<_Args>()...)
+  )>
+  _LIBCPP_HIDE_FROM_ABI
+  constexpr _Tp* operator()(_Tp* __location, _Args&& ...__args) const {
+    return _VSTD::construct_at(__location, _VSTD::forward<_Args>(__args)...);
+  }
+
+};
+
+} // namespace __construct_at
+
+inline namespace __cpo {
+inline constexpr auto construct_at = __construct_at::__fn(__function_like::__tag());
+} // namespace __cpo
+
+// destroy_at
+
+namespace __destroy_at {
+
+struct __fn final : private __function_like {
+
+  _LIBCPP_HIDE_FROM_ABI
+  constexpr explicit __fn(__tag __x) noexcept : __function_like(__x) {}
+
+  template <destructible _Tp>
+  _LIBCPP_HIDE_FROM_ABI
+  constexpr void operator()(_Tp* __location) const noexcept {
+    _VSTD::destroy_at(__location);
+  }
+
+};
+
+} // namespace __destroy_at
+
+inline namespace __cpo {
+inline constexpr auto destroy_at = __destroy_at::__fn(__function_like::__tag());
+} // namespace __cpo
+
+// destroy
+
+namespace __destroy {
+
+struct __fn final : private __function_like {
+
+  _LIBCPP_HIDE_FROM_ABI
+  constexpr explicit __fn(__tag __x) noexcept : __function_like(__x) {}
+
+  template <__nothrow_input_iterator _InputIterator, __nothrow_sentinel_for<_InputIterator> _Sentinel>
+    requires destructible<iter_value_t<_InputIterator>>
+  _LIBCPP_HIDE_FROM_ABI
+  constexpr _InputIterator operator()(_InputIterator __first, _Sentinel __last) const noexcept {
+    return _VSTD::__destroy(_VSTD::move(__first), _VSTD::move(__last));
+  }
+
+  template <__nothrow_input_range _InputRange>
+    requires destructible<range_value_t<_InputRange>>
+  _LIBCPP_HIDE_FROM_ABI
+  constexpr borrowed_iterator_t<_InputRange> operator()(_InputRange&& __range) const noexcept {
+    return (*this)(ranges::begin(__range), ranges::end(__range));
+  }
+
+};
+
+} // namespace __destroy
+
+inline namespace __cpo {
+inline constexpr auto destroy = __destroy::__fn(__function_like::__tag());
+} // namespace __cpo
+
+// destroy_n
+
+namespace __destroy_n {
+
+struct __fn final : private __function_like {
+
+  _LIBCPP_HIDE_FROM_ABI
+  constexpr explicit __fn(__tag __x) noexcept : __function_like(__x) {}
+
+  template <__nothrow_input_iterator _InputIterator>
+    requires destructible<iter_value_t<_InputIterator>>
+  _LIBCPP_HIDE_FROM_ABI
+  constexpr _InputIterator operator()(_InputIterator __first, iter_difference_t<_InputIterator> __n) const noexcept {
+    return _VSTD::destroy_n(_VSTD::move(__first), __n);
+  }
+
+};
+
+} // namespace __destroy_n
+
+inline namespace __cpo {
+inline constexpr auto destroy_n = __destroy_n::__fn(__function_like::__tag());
+} // namespace __cpo
+
+} // namespace ranges
+#endif // !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___MEMORY_RANGES_CONSTRUCT_AT_H
diff --git a/include/memory b/include/memory
index 244b40f..db59936 100644
--- a/include/memory
+++ b/include/memory
@@ -244,15 +244,40 @@
 template <class T, class ...Args>
 constexpr T* construct_at(T* location, Args&& ...args); // since C++20
 
+namespace ranges {
+  template<class T, class... Args>
+    constexpr T* construct_at(T* location, Args&&... args); // since C++20
+}
+
 template <class T>
 void destroy_at(T* location); // constexpr in C++20
 
+namespace ranges {
+  template<destructible T>
+    constexpr void destroy_at(T* location) noexcept; // since C++20
+}
+
 template <class ForwardIterator>
 void destroy(ForwardIterator first, ForwardIterator last); // constexpr in C++20
 
+namespace ranges {
+  template<nothrow-input-iterator InputIterator, nothrow-sentinel-for<InputIterator> Sentinel>
+    requires destructible<iter_value_t<InputIterator>>
+    constexpr InputIterator destroy(InputIterator first, Sentinel last) noexcept; // since C++20
+  template<nothrow-input-range InputRange>
+    requires destructible<range_value_t<InputRange>>
+    constexpr borrowed_iterator_t<InputRange> destroy(InputRange&& range) noexcept; // since C++20
+}
+
 template <class ForwardIterator, class Size>
 ForwardIterator destroy_n(ForwardIterator first, Size n); // constexpr in C++20
 
+namespace ranges {
+  template<nothrow-input-iterator InputIterator>
+    requires destructible<iter_value_t<InputIterator>>
+    constexpr InputIterator destroy_n(InputIterator first, iter_difference_t<InputIterator> n) noexcept; // since C++20
+}
+
 template <class InputIterator, class ForwardIterator>
  ForwardIterator uninitialized_move(InputIterator first, InputIterator last, ForwardIterator result);
 
@@ -790,6 +815,7 @@
 #include <__memory/concepts.h>
 #include <__memory/construct_at.h>
 #include <__memory/pointer_traits.h>
+#include <__memory/ranges_construct_at.h>
 #include <__memory/ranges_uninitialized_algorithms.h>
 #include <__memory/raw_storage_iterator.h>
 #include <__memory/shared_ptr.h>
diff --git a/include/module.modulemap b/include/module.modulemap
index 305fe1b..828c9d5 100644
--- a/include/module.modulemap
+++ b/include/module.modulemap
@@ -661,6 +661,10 @@
       module concepts                        { private header "__memory/concepts.h" }
       module construct_at                    { private header "__memory/construct_at.h" }
       module pointer_traits                  { private header "__memory/pointer_traits.h" }
+      module ranges_construct_at {
+        private header "__memory/ranges_construct_at.h"
+        export __function_like
+      }
       module ranges_uninitialized_algorithms {
         private header "__memory/ranges_uninitialized_algorithms.h"
         export __function_like