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