Actual source code: memory.hpp
1: #pragma once
3: #include <petsc/private/cpp/utility.hpp>
4: #if PETSC_CPP_VERSION < 14
5: #include <petsc/private/cpp/type_traits.hpp>
6: #endif
8: #include <memory>
10: namespace Petsc
11: {
13: namespace util
14: {
16: #if PETSC_CPP_VERSION >= 14
17: using std::make_unique;
18: #else
19: namespace detail
20: {
22: // helpers shamelessly stolen from libcpp
23: template <class T>
24: struct unique_if {
25: using unique_single = std::unique_ptr<T>;
26: };
28: template <class T>
29: struct unique_if<T[]> {
30: using unique_array_unknown_bound = std::unique_ptr<T[]>;
31: };
33: template <class T, std::size_t N>
34: struct unique_if<T[N]> {
35: using unique_array_unknown_bound = void;
36: };
38: } // namespace detail
40: template <class T, class... Args>
41: inline typename detail::unique_if<T>::unique_single make_unique(Args &&...args)
42: {
43: return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
44: }
46: template <class T>
47: inline typename detail::unique_if<T>::unique_array_unknown_bound make_unique(std::size_t n)
48: {
49: return std::unique_ptr<T>(new util::remove_extent_t<T>[n]());
50: }
52: template <class T, class... Args>
53: typename detail::unique_if<T>::unique_array_known_bound make_unique(Args &&...) = delete;
54: #endif // PETSC_CPP_VERSION >= 14
56: #if PETSC_CPP_VERSION >= 20
57: // only use std::destroy_at from C++20 onwards (even though it was introduced in C++17) since
58: // that makes the behavior more uniform for arrays.
59: using std::destroy_at;
60: using std::construct_at;
61: #else
62: template <class T>
63: inline enable_if_t<!std::is_array<T>::value> destroy_at(T *ptr) noexcept(std::is_nothrow_destructible<T>::value)
64: {
65: ptr->~T();
66: }
68: template <class T>
69: inline enable_if_t<std::is_array<T>::value> destroy_at(T *ptr)
70: {
71: for (auto &elem : *ptr) destroy_at(std::addressof(elem));
72: }
74: template <class T, class... Args, class = decltype(::new (std::declval<void *>()) T{std::declval<Args>()...})>
75: inline constexpr T *construct_at(T *ptr, Args &&...args) noexcept(std::is_nothrow_constructible<T, Args...>::value)
76: {
77: return ::new ((void *)ptr) T{std::forward<Args>(args)...};
78: }
79: #endif
81: } // namespace util
83: } // namespace Petsc