[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