/* * This file is part of the DXX-Rebirth project . * It is copyright by its individual contributors, as recorded in the * project's Git history. See COPYING.txt at the top level for license * terms and a link to the Git history. */ #include #include namespace dcx { /* `unique_span` wraps `unique_ptr`, but also remembers the extent of the * array `T[]`. The method `span()` returns a * `std::span` that covers the memory region managed by * `unique_span`. There is no support for a `std::span`, * because that could be more simply handled by * `std::unique_ptr>`, which would avoid * storing the extent in the `unique_span`. */ /* Set a default deleter from the underlying unique_ptr, but allow it to be * overridden if the caller needs special handling. */ template ::deleter_type> class unique_span : std::unique_ptr { using base_type = std::unique_ptr; std::size_t extent{}; public: constexpr unique_span() = default; constexpr unique_span(base_type &&b, const std::size_t e) : base_type(std::move(b)), extent(e) { } unique_span(const std::size_t e) : base_type(new T[e]()), extent(e) { } unique_span(unique_span &&) = default; unique_span &operator=(unique_span &&) = default; using base_type::get; /* Require an lvalue input, since the returned pointer is borrowed from * this object. If the method is called on an rvalue input, then the * unique_ptr would be destroyed and free the memory before the returned * span was destroyed, which would leave the span dangling. */ [[nodiscard]] std::span span() & { return {get(), extent}; } [[nodiscard]] std::span span() const & { return {get(), extent}; } std::span span() const && = delete; auto release() { extent = 0; return this->base_type::release(); } std::size_t size() const { return extent; } }; }