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