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