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