#pragma once #include // PETSC_CPP_VERSION #include #if PETSC_CPP_VERSION < 14 #include // remove_extent #endif #include namespace Petsc { namespace util { #if PETSC_CPP_VERSION >= 14 using std::make_unique; #else namespace detail { // helpers shamelessly stolen from libcpp template struct unique_if { using unique_single = std::unique_ptr; }; template struct unique_if { using unique_array_unknown_bound = std::unique_ptr; }; template struct unique_if { using unique_array_unknown_bound = void; }; } // namespace detail template inline typename detail::unique_if::unique_single make_unique(Args &&...args) { return std::unique_ptr(new T(std::forward(args)...)); } template inline typename detail::unique_if::unique_array_unknown_bound make_unique(std::size_t n) { return std::unique_ptr(new util::remove_extent_t[n]()); } template typename detail::unique_if::unique_array_known_bound make_unique(Args &&...) = delete; #endif // PETSC_CPP_VERSION >= 14 #if PETSC_CPP_VERSION >= 20 // only use std::destroy_at from C++20 onwards (even though it was introduced in C++17) since // that makes the behavior more uniform for arrays. using std::destroy_at; using std::construct_at; #else template inline enable_if_t::value> destroy_at(T *ptr) noexcept(std::is_nothrow_destructible::value) { ptr->~T(); } template inline enable_if_t::value> destroy_at(T *ptr) { for (auto &elem : *ptr) destroy_at(std::addressof(elem)); } template ()) T{std::declval()...})> inline constexpr T *construct_at(T *ptr, Args &&...args) noexcept(std::is_nothrow_constructible::value) { return ::new ((void *)ptr) T{std::forward(args)...}; } #endif } // namespace util } // namespace Petsc