1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP___MEMORY_CONSTRUCT_AT_H
11#define _LIBCPP___MEMORY_CONSTRUCT_AT_H
12
13#include <__assert>
14#include <__config>
15#include <__memory/addressof.h>
16#include <__new/placement_new_delete.h>
17#include <__type_traits/is_array.h>
18#include <__utility/declval.h>
19#include <__utility/forward.h>
20
21#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
22# pragma GCC system_header
23#endif
24
25_LIBCPP_PUSH_MACROS
26#include <__undef_macros>
27
28_LIBCPP_BEGIN_NAMESPACE_STD
29
30// construct_at
31
32#if _LIBCPP_STD_VER >= 20
33
34template <class _Tp, class... _Args, class = decltype(::new(std::declval<void*>()) _Tp(std::declval<_Args>()...))>
35_LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* _LIBCPP_DIAGNOSE_NULLPTR __location, _Args&&... __args) {
36 _LIBCPP_ASSERT_NON_NULL(__location != nullptr, "null pointer given to construct_at");
37 return ::new (static_cast<void*>(__location)) _Tp(std::forward<_Args>(__args)...);
38}
39
40#endif
41
42template <class _Tp, class... _Args, class = decltype(::new(std::declval<void*>()) _Tp(std::declval<_Args>()...))>
43_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp* __construct_at(_Tp* __location, _Args&&... __args) {
44#if _LIBCPP_STD_VER >= 20
45 return std::construct_at(__location, std::forward<_Args>(__args)...);
46#else
47 return _LIBCPP_ASSERT_NON_NULL(__location != nullptr, "null pointer given to construct_at"),
48 ::new (static_cast<void*>(__location)) _Tp(std::forward<_Args>(__args)...);
49#endif
50}
51
52// destroy_at
53
54// The internal functions are available regardless of the language version (with the exception of the `__destroy_at`
55// taking an array).
56
57template <class _Tp>
58_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __destroy_at(_Tp* __loc) {
59 _LIBCPP_ASSERT_NON_NULL(__loc != nullptr, "null pointer given to destroy_at");
60#if _LIBCPP_STD_VER >= 20
61 if constexpr (is_array_v<_Tp>) {
62 for (auto&& __val : *__loc)
63 std::__destroy_at(std::addressof(__val));
64 } else
65#endif
66 {
67 __loc->~_Tp();
68 }
69}
70
71#if _LIBCPP_STD_VER >= 17
72template <class _Tp>
73_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy_at(_Tp* _LIBCPP_DIAGNOSE_NULLPTR __loc) {
74 std::__destroy_at(__loc);
75}
76#endif // _LIBCPP_STD_VER >= 17
77
78_LIBCPP_END_NAMESPACE_STD
79
80_LIBCPP_POP_MACROS
81
82#endif // _LIBCPP___MEMORY_CONSTRUCT_AT_H
83