From def67bba57e7cfdf9942bc2c88a4ce484963f9d2 Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Fri, 6 Sep 2024 23:22:18 +0200 Subject: maybe_uninit --- asl/BUILD.bazel | 5 ++++- asl/annotations.hpp | 11 +++++++++++ asl/layout.hpp | 29 +++++++++++++++++++++++++++++ asl/maybe_uninit.hpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ asl/maybe_uninit_tests.cpp | 7 +++++++ asl/memory.hpp | 8 ++++++++ 6 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 asl/layout.hpp create mode 100644 asl/maybe_uninit.hpp create mode 100644 asl/maybe_uninit_tests.cpp create mode 100644 asl/memory.hpp (limited to 'asl') diff --git a/asl/BUILD.bazel b/asl/BUILD.bazel index e5d5eb3..d7371c1 100644 --- a/asl/BUILD.bazel +++ b/asl/BUILD.bazel @@ -3,6 +3,9 @@ cc_library( hdrs = [ "annotations.hpp", "integers.hpp", + "layout.hpp", + "maybe_uninit.hpp", + "memory.hpp", "meta.hpp", "option.hpp", "utility.hpp", @@ -19,4 +22,4 @@ cc_library( deps = [ ":asl", ], -) for name in ["integers", "meta", "option", "utility"]] +) for name in ["integers", "maybe_uninit", "meta", "option", "utility"]] diff --git a/asl/annotations.hpp b/asl/annotations.hpp index a94834d..c0d8f20 100644 --- a/asl/annotations.hpp +++ b/asl/annotations.hpp @@ -10,3 +10,14 @@ #define ASL_NO_UNIQUE_ADDRESS [[no_unique_address]] #endif +namespace asl +{ + +struct unsafe +{ + unsafe() = delete; + explicit unsafe(auto&&) {} +}; + +} // namespace asl + diff --git a/asl/layout.hpp b/asl/layout.hpp new file mode 100644 index 0000000..5141456 --- /dev/null +++ b/asl/layout.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "asl/integers.hpp" +#include "asl/meta.hpp" + +namespace asl +{ + +template +inline constexpr int64_t size_of = static_cast(sizeof(T)); + +template +inline constexpr int64_t align_of = static_cast(alignof(T)); + +struct layout +{ + int64_t size; + int64_t align; + + constexpr bool operator==(const layout&) const = default; + + template + static constexpr layout of() + { + return layout{ size_of, align_of }; + } +}; + +} // namespace asl diff --git a/asl/maybe_uninit.hpp b/asl/maybe_uninit.hpp new file mode 100644 index 0000000..ffbbb1c --- /dev/null +++ b/asl/maybe_uninit.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include "asl/annotations.hpp" +#include "asl/layout.hpp" +#include "asl/memory.hpp" +#include "asl/meta.hpp" + +namespace asl +{ + +template +class alignas(align_of) maybe_uninit +{ + char m_storage[size_of]; + +public: + constexpr void* uninit_ptr() const { return m_storage; } + + // @Safety Pointer must only be accessed when in initialized state. + constexpr const T* init_ptr(unsafe) const { return reinterpret_cast(m_storage); } + constexpr T* init_ptr(unsafe) { return reinterpret_cast< T*>(m_storage); } + + // @Safety Reference must only be accessed when in initialized state. + constexpr const T& as_init(unsafe) const { return *reinterpret_cast(m_storage); } + constexpr T& as_init(unsafe) { return *reinterpret_cast< T*>(m_storage); } + + // @Safety Must be called only when in uninitialized state. + template + inline void init(unsafe, Args&&... args) + { + new(uninit_ptr()) T(ASL_FWD(args)...); + } + + // @Safety Must be called only when in initialized state. + inline void uninit(unsafe) + { + if constexpr (!trivially_destructible) + { + init_ptr(unsafe("Caller has checked init state"))->~T(); + } + } +}; + +} // namespace asl diff --git a/asl/maybe_uninit_tests.cpp b/asl/maybe_uninit_tests.cpp new file mode 100644 index 0000000..7efeff0 --- /dev/null +++ b/asl/maybe_uninit_tests.cpp @@ -0,0 +1,7 @@ +#include "asl/maybe_uninit.hpp" + +static_assert(asl::layout::of() == asl::layout::of>()); +static_assert(asl::size_of == asl::size_of>); +static_assert(asl::align_of == asl::align_of>); + +int main() { return 0; } diff --git a/asl/memory.hpp b/asl/memory.hpp new file mode 100644 index 0000000..33fa819 --- /dev/null +++ b/asl/memory.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include "asl/integers.hpp" + +constexpr void* operator new(uint64_t, void* ptr) +{ + return ptr; +} -- cgit