xref: /freebsd-src/contrib/llvm-project/libcxx/include/__memory/construct_at.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1fe6060f1SDimitry Andric // -*- C++ -*-
2fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
3fe6060f1SDimitry Andric //
4fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7fe6060f1SDimitry Andric //
8fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
9fe6060f1SDimitry Andric 
10fe6060f1SDimitry Andric #ifndef _LIBCPP___MEMORY_CONSTRUCT_AT_H
11fe6060f1SDimitry Andric #define _LIBCPP___MEMORY_CONSTRUCT_AT_H
12fe6060f1SDimitry Andric 
1381ad6265SDimitry Andric #include <__assert>
14fe6060f1SDimitry Andric #include <__config>
15349cc55cSDimitry Andric #include <__iterator/access.h>
16349cc55cSDimitry Andric #include <__memory/addressof.h>
1704eeddc0SDimitry Andric #include <__memory/voidify.h>
18bdd1243dSDimitry Andric #include <__type_traits/enable_if.h>
19bdd1243dSDimitry Andric #include <__type_traits/is_array.h>
20bdd1243dSDimitry Andric #include <__utility/declval.h>
21fe6060f1SDimitry Andric #include <__utility/forward.h>
2281ad6265SDimitry Andric #include <__utility/move.h>
23bdd1243dSDimitry Andric #include <new>
24fe6060f1SDimitry Andric 
25fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
26fe6060f1SDimitry Andric #  pragma GCC system_header
27fe6060f1SDimitry Andric #endif
28fe6060f1SDimitry Andric 
2906c3fb27SDimitry Andric _LIBCPP_PUSH_MACROS
3006c3fb27SDimitry Andric #include <__undef_macros>
3106c3fb27SDimitry Andric 
32fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
33fe6060f1SDimitry Andric 
34fe6060f1SDimitry Andric // construct_at
35fe6060f1SDimitry Andric 
3606c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
37fe6060f1SDimitry Andric 
38bdd1243dSDimitry Andric template <class _Tp, class... _Args, class = decltype(::new(std::declval<void*>()) _Tp(std::declval<_Args>()...))>
3981ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* __location, _Args&&... __args) {
405f757f3fSDimitry Andric   _LIBCPP_ASSERT_NON_NULL(__location != nullptr, "null pointer given to construct_at");
4106c3fb27SDimitry Andric   return ::new (std::__voidify(*__location)) _Tp(std::forward<_Args>(__args)...);
42fe6060f1SDimitry Andric }
43fe6060f1SDimitry Andric 
44fe6060f1SDimitry Andric #endif
45fe6060f1SDimitry Andric 
46bdd1243dSDimitry Andric template <class _Tp, class... _Args, class = decltype(::new(std::declval<void*>()) _Tp(std::declval<_Args>()...))>
47*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp* __construct_at(_Tp* __location, _Args&&... __args) {
4806c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
4981ad6265SDimitry Andric   return std::construct_at(__location, std::forward<_Args>(__args)...);
5081ad6265SDimitry Andric #else
515f757f3fSDimitry Andric   return _LIBCPP_ASSERT_NON_NULL(__location != nullptr, "null pointer given to construct_at"),
5261cfbce3SDimitry Andric          ::new (std::__voidify(*__location)) _Tp(std::forward<_Args>(__args)...);
5381ad6265SDimitry Andric #endif
5481ad6265SDimitry Andric }
5581ad6265SDimitry Andric 
56fe6060f1SDimitry Andric // destroy_at
57fe6060f1SDimitry Andric 
580eae32dcSDimitry Andric // The internal functions are available regardless of the language version (with the exception of the `__destroy_at`
590eae32dcSDimitry Andric // taking an array).
60fe6060f1SDimitry Andric 
61349cc55cSDimitry Andric template <class _ForwardIterator>
62cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator __destroy(_ForwardIterator, _ForwardIterator);
630eae32dcSDimitry Andric 
645f757f3fSDimitry Andric template <class _Tp, __enable_if_t<!is_array<_Tp>::value, int> = 0>
65cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __destroy_at(_Tp* __loc) {
665f757f3fSDimitry Andric   _LIBCPP_ASSERT_NON_NULL(__loc != nullptr, "null pointer given to destroy_at");
670eae32dcSDimitry Andric   __loc->~_Tp();
680eae32dcSDimitry Andric }
690eae32dcSDimitry Andric 
7006c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
715f757f3fSDimitry Andric template <class _Tp, __enable_if_t<is_array<_Tp>::value, int> = 0>
72cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __destroy_at(_Tp* __loc) {
735f757f3fSDimitry Andric   _LIBCPP_ASSERT_NON_NULL(__loc != nullptr, "null pointer given to destroy_at");
7406c3fb27SDimitry Andric   std::__destroy(std::begin(*__loc), std::end(*__loc));
750eae32dcSDimitry Andric }
760eae32dcSDimitry Andric #endif
770eae32dcSDimitry Andric 
780eae32dcSDimitry Andric template <class _ForwardIterator>
79cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
80cb14a3feSDimitry Andric __destroy(_ForwardIterator __first, _ForwardIterator __last) {
810eae32dcSDimitry Andric   for (; __first != __last; ++__first)
8206c3fb27SDimitry Andric     std::__destroy_at(std::addressof(*__first));
8304eeddc0SDimitry Andric   return __first;
840eae32dcSDimitry Andric }
850eae32dcSDimitry Andric 
861ac55f4cSDimitry Andric template <class _BidirectionalIterator>
87cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _BidirectionalIterator
88cb14a3feSDimitry Andric __reverse_destroy(_BidirectionalIterator __first, _BidirectionalIterator __last) {
891ac55f4cSDimitry Andric   while (__last != __first) {
901ac55f4cSDimitry Andric     --__last;
911ac55f4cSDimitry Andric     std::__destroy_at(std::addressof(*__last));
921ac55f4cSDimitry Andric   }
931ac55f4cSDimitry Andric   return __last;
941ac55f4cSDimitry Andric }
951ac55f4cSDimitry Andric 
9606c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 17
97349cc55cSDimitry Andric 
98349cc55cSDimitry Andric template <class _Tp, enable_if_t<!is_array_v<_Tp>, int> = 0>
99cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy_at(_Tp* __loc) {
10006c3fb27SDimitry Andric   std::__destroy_at(__loc);
101fe6060f1SDimitry Andric }
102fe6060f1SDimitry Andric 
10306c3fb27SDimitry Andric #  if _LIBCPP_STD_VER >= 20
104349cc55cSDimitry Andric template <class _Tp, enable_if_t<is_array_v<_Tp>, int> = 0>
105cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy_at(_Tp* __loc) {
10606c3fb27SDimitry Andric   std::__destroy_at(__loc);
107349cc55cSDimitry Andric }
108349cc55cSDimitry Andric #  endif
109349cc55cSDimitry Andric 
110349cc55cSDimitry Andric template <class _ForwardIterator>
111cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy(_ForwardIterator __first, _ForwardIterator __last) {
11206c3fb27SDimitry Andric   (void)std::__destroy(std::move(__first), std::move(__last));
113349cc55cSDimitry Andric }
114349cc55cSDimitry Andric 
115349cc55cSDimitry Andric template <class _ForwardIterator, class _Size>
116cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator destroy_n(_ForwardIterator __first, _Size __n) {
117349cc55cSDimitry Andric   for (; __n > 0; (void)++__first, --__n)
11806c3fb27SDimitry Andric     std::__destroy_at(std::addressof(*__first));
119349cc55cSDimitry Andric   return __first;
120349cc55cSDimitry Andric }
121349cc55cSDimitry Andric 
12206c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 17
123fe6060f1SDimitry Andric 
124fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
125fe6060f1SDimitry Andric 
12606c3fb27SDimitry Andric _LIBCPP_POP_MACROS
12706c3fb27SDimitry Andric 
128fe6060f1SDimitry Andric #endif // _LIBCPP___MEMORY_CONSTRUCT_AT_H
129