1 #pragma once 2 3 #include <petscmacros.h> // PETSC_CPP_VERSION 4 5 #include <petsc/private/cpp/utility.hpp> 6 #if PETSC_CPP_VERSION < 14 7 #include <petsc/private/cpp/type_traits.hpp> // remove_extent 8 #endif 9 10 #include <memory> 11 12 namespace Petsc 13 { 14 15 namespace util 16 { 17 18 #if PETSC_CPP_VERSION >= 14 19 using std::make_unique; 20 #else 21 namespace detail 22 { 23 24 // helpers shamelessly stolen from libcpp 25 template <class T> 26 struct unique_if { 27 using unique_single = std::unique_ptr<T>; 28 }; 29 30 template <class T> 31 struct unique_if<T[]> { 32 using unique_array_unknown_bound = std::unique_ptr<T[]>; 33 }; 34 35 template <class T, std::size_t N> 36 struct unique_if<T[N]> { 37 using unique_array_unknown_bound = void; 38 }; 39 40 } // namespace detail 41 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 } 47 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 } 53 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 57 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> destroy_at(T * ptr)65inline enable_if_t<!std::is_array<T>::value> destroy_at(T *ptr) noexcept(std::is_nothrow_destructible<T>::value) 66 { 67 ptr->~T(); 68 } 69 70 template <class T> destroy_at(T * ptr)71inline enable_if_t<std::is_array<T>::value> destroy_at(T *ptr) 72 { 73 for (auto &elem : *ptr) destroy_at(std::addressof(elem)); 74 } 75 76 template <class T, class... Args, class = decltype(::new (std::declval<void *>()) T{std::declval<Args>()...})> construct_at(T * ptr,Args &&...args)77inline 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 82 83 } // namespace util 84 85 } // namespace Petsc 86