From 3006e77ef371ff64e57a9a430f9a4ee8f353bb67 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Tue, 12 Aug 2025 22:37:21 -0500 Subject: [PATCH] [ox/std] Add and integrate std::launder --- deps/ox/src/ox/std/new.hpp | 38 ++++++++++++++++++++++++ deps/ox/src/ox/std/types.hpp | 19 ------------ deps/ox/src/ox/std/vector.hpp | 54 ++++++++++++----------------------- 3 files changed, 57 insertions(+), 54 deletions(-) diff --git a/deps/ox/src/ox/std/new.hpp b/deps/ox/src/ox/std/new.hpp index 450a999b..26af0459 100644 --- a/deps/ox/src/ox/std/new.hpp +++ b/deps/ox/src/ox/std/new.hpp @@ -30,11 +30,49 @@ constexpr void *operator new(std::size_t, void *addr) noexcept { constexpr void *operator new[](std::size_t, void *addr) noexcept { return addr; } + +namespace std { + +template +[[nodiscard]] +constexpr T* launder(T* __p) noexcept { + return __builtin_launder(__p); +} + +template +void launder(T(*)(Args...) noexcept(noex)) = delete; +template +void launder(T(*)(Args......) noexcept(noex)) = delete; +void launder(void*) = delete; +void launder(void const*) = delete; +void launder(volatile void*) = delete; +void launder(volatile void const*) = delete; + +} #endif namespace ox { +/** + * Aliases type T in size and alignment to allow allocating space for a T + * without running the constructor. + */ +template +struct alignas(alignof(T)) AllocAlias { + char buff[sz]; + constexpr AllocAlias() noexcept = default; + [[nodiscard]] + auto data() noexcept { + return reinterpret_cast(this); + } + [[nodiscard]] + auto data() const noexcept { + return reinterpret_cast(this); + } +}; + + template [[nodiscard]] constexpr U *make(Args &&...args) noexcept { diff --git a/deps/ox/src/ox/std/types.hpp b/deps/ox/src/ox/std/types.hpp index a441f089..1cf77e82 100644 --- a/deps/ox/src/ox/std/types.hpp +++ b/deps/ox/src/ox/std/types.hpp @@ -63,25 +63,6 @@ namespace ox { using CString = char const*; -/** - * Aliases type T in size and alignment to allow allocating space for a T - * without running the constructor. - */ -template -struct alignas(alignof(T)) AllocAlias { - char buff[sz]; - constexpr AllocAlias() noexcept = default; - [[nodiscard]] - auto data() noexcept { - return reinterpret_cast(this); - } - [[nodiscard]] - auto data() const noexcept { - return reinterpret_cast(this); - } -}; - - template struct SignedType { }; diff --git a/deps/ox/src/ox/std/vector.hpp b/deps/ox/src/ox/std/vector.hpp index aa570621..97d694cc 100644 --- a/deps/ox/src/ox/std/vector.hpp +++ b/deps/ox/src/ox/std/vector.hpp @@ -34,10 +34,10 @@ struct VectorAllocator { ox::Array, Size> m_data = {}; protected: constexpr VectorAllocator() noexcept = default; - constexpr VectorAllocator(const VectorAllocator&) noexcept = default; + constexpr VectorAllocator(VectorAllocator const&) noexcept = default; constexpr VectorAllocator(VectorAllocator&&) noexcept = default; - constexpr void allocate(T **items, std::size_t cap) noexcept { + constexpr void allocate(T **items, std::size_t const cap) noexcept { // small vector optimization cannot be done it constexpr, but it doesn't really matter in constexpr if (std::is_constant_evaluated() || cap > Size) { *items = Allocator{}.allocate(cap); @@ -49,42 +49,26 @@ struct VectorAllocator { constexpr void moveConstructItemsFrom( T **items, VectorAllocator *src, - const std::size_t count, - const std::size_t cap) noexcept { + std::size_t const count, + std::size_t const cap) noexcept { // this totally idiotic redundant check (&& count <= Size) is required to address a bug in devkitARM, // try removing it later if (!std::is_constant_evaluated()) { if (cap <= m_data.size() && count <= m_data.size()) { for (auto i = 0u; i < count; ++i) { - const auto dstItem = reinterpret_cast(&m_data[i]); - const auto srcItem = reinterpret_cast(&src->m_data[i]); - std::construct_at(dstItem, std::move(*srcItem)); + auto const srcItem = std::launder(reinterpret_cast(&src->m_data[i])); + new (&m_data[i]) T(std::move(*srcItem)); + } + if (count) { + *items = std::launder(reinterpret_cast(m_data.data())); + } else { + *items = reinterpret_cast(m_data.data()); } - *items = reinterpret_cast(m_data.data()); } } } - constexpr void moveItemsFrom( - T **items, - VectorAllocator *src, - const std::size_t count, - const std::size_t cap) noexcept { - // this totally idiotic redundant check (&& count <= Size) is required to address a bug in devkitARM, - // try removing it later - if (!std::is_constant_evaluated()) { - if (cap <= m_data.size() && count <= m_data.size()) { - for (std::size_t i = 0; i < count; ++i) { - const auto dstItem = reinterpret_cast(&m_data[i]); - const auto srcItem = reinterpret_cast(&src->m_data[i]); - *dstItem = std::move(*srcItem); - } - *items = reinterpret_cast(m_data.data()); - } - } - } - - constexpr void deallocate(T *items, std::size_t cap) noexcept { + constexpr void deallocate(T *const items, std::size_t const cap) noexcept { // small vector optimization cannot be done it constexpr, but it doesn't really matter in constexpr if (std::is_constant_evaluated()) { if (items) { @@ -103,10 +87,10 @@ template struct VectorAllocator { protected: constexpr VectorAllocator() noexcept = default; - constexpr VectorAllocator(const VectorAllocator&) noexcept = default; + constexpr VectorAllocator(VectorAllocator const&) noexcept = default; constexpr VectorAllocator(VectorAllocator&&) noexcept = default; - constexpr void allocate(T **items, std::size_t cap) noexcept { + constexpr void allocate(T **items, std::size_t const cap) noexcept { *items = Allocator{}.allocate(cap); } @@ -114,15 +98,15 @@ struct VectorAllocator { constexpr void moveConstructItemsFrom( T**, VectorAllocator*, - const std::size_t, - const std::size_t) noexcept { + std::size_t const, + std::size_t const) noexcept { } [[maybe_unused]] - constexpr void moveItemsFrom(T**, VectorAllocator*, const std::size_t, const std::size_t) noexcept { + constexpr void moveItemsFrom(T**, VectorAllocator*, std::size_t const, std::size_t const) noexcept { } - constexpr void deallocate(T *items, std::size_t cap) noexcept { + constexpr void deallocate(T *const items, std::size_t const cap) noexcept { if (items) { Allocator{}.deallocate(items, cap); } @@ -421,7 +405,7 @@ constexpr Vector &VectormoveItemsFrom(&m_items, &other, m_size, m_cap); + this->moveConstructItemsFrom(&m_items, &other, m_size, m_cap); other.m_size = 0; other.m_cap = 0; other.m_items = nullptr;