summaryrefslogtreecommitdiff
path: root/asl/maybe_uninit.hpp
diff options
context:
space:
mode:
authorSteven Le Rouzic <steven.lerouzic@gmail.com>2025-01-05 15:25:45 +0100
committerSteven Le Rouzic <steven.lerouzic@gmail.com>2025-01-05 15:25:45 +0100
commit8607772d4f9e21f53c1abfd9379737403b97f430 (patch)
treefcd5a5030bb1cc0ba4dd4069a0d7174a67791c03 /asl/maybe_uninit.hpp
parentb53fc9038f4579974c9eea28e82b693a7fd66522 (diff)
Fix a few mistakes in option, and make it trivial when possible
Diffstat (limited to 'asl/maybe_uninit.hpp')
-rw-r--r--asl/maybe_uninit.hpp82
1 files changed, 47 insertions, 35 deletions
diff --git a/asl/maybe_uninit.hpp b/asl/maybe_uninit.hpp
index e59cfe0..4f60e4d 100644
--- a/asl/maybe_uninit.hpp
+++ b/asl/maybe_uninit.hpp
@@ -1,60 +1,72 @@
#pragma once
-#include "asl/layout.hpp"
-#include "asl/memory.hpp"
#include "asl/meta.hpp"
#include "asl/utility.hpp"
+#include "asl/memory.hpp"
namespace asl
{
template<is_object T>
-class maybe_uninit
+union maybe_uninit
{
- union
- {
- alignas(align_of<T>) char m_storage[size_of<T>];
- T m_value;
- };
+private:
+ T m_value;
public:
- constexpr maybe_uninit() {} // NOLINT(*-member-init)
+ constexpr maybe_uninit() requires trivially_default_constructible<T> = default;
+ constexpr maybe_uninit() requires (!trivially_default_constructible<T>) {} // NOLINT
- maybe_uninit(const maybe_uninit&) = delete;
- maybe_uninit(maybe_uninit&&) = delete;
-
- maybe_uninit& operator=(const maybe_uninit&) = delete;
- maybe_uninit& operator=(maybe_uninit&&) = delete;
+ template<typename... Args>
+ explicit constexpr maybe_uninit(in_place_t, Args&&... args)
+ requires constructible_from<T, Args&&...>
+ : m_value{ASL_FWD(args)...}
+ {}
- constexpr ~maybe_uninit() = default;
- constexpr ~maybe_uninit() requires (!trivially_destructible<T>) {}
+ constexpr maybe_uninit(const maybe_uninit&) requires trivially_copy_constructible<T> = default;
+ constexpr maybe_uninit(const maybe_uninit&) requires (!trivially_copy_constructible<T>) {} // NOLINT
- constexpr void* uninit_ptr() && = delete;
- constexpr const void* uninit_ptr() const& { return m_storage; }
- constexpr void* uninit_ptr() & { return m_storage; }
-
- // @Safety Pointer must only be accessed when in initialized state.
- constexpr T* init_ptr_unsafe() && = delete;
- constexpr const T* init_ptr_unsafe() const& { return &m_value; }
- constexpr T* init_ptr_unsafe() & { return &m_value; }
-
- // @Safety Reference must only be accessed when in initialized state.
- constexpr T&& as_init_unsafe() && { return ASL_MOVE(m_value); }
- constexpr const T& as_init_unsafe() const& { return m_value; }
- constexpr T& as_init_unsafe() & { return m_value; }
+ constexpr maybe_uninit(maybe_uninit&&) requires trivially_move_constructible<T> = default;
+ constexpr maybe_uninit(maybe_uninit&&) requires (!trivially_move_constructible<T>) {} // NOLINT
+
+ constexpr maybe_uninit& operator=(const maybe_uninit&) requires trivially_copy_assignable<T> = default;
+ constexpr maybe_uninit& operator=(const maybe_uninit&) requires (!trivially_copy_assignable<T>) {}
+
+ constexpr maybe_uninit& operator=(maybe_uninit&&) requires trivially_move_assignable<T> = default;
+ constexpr maybe_uninit& operator=(maybe_uninit&&) requires (!trivially_move_assignable<T>) {}
+
+ constexpr ~maybe_uninit() requires trivially_destructible<T> = default;
+ constexpr ~maybe_uninit() requires (!trivially_destructible<T>) {} // NOLINT
- // @Safety Must be called only when in uninitialized state.
+ // @Safety Value must not have been initialized yet
template<typename... Args>
- constexpr void init_unsafe(Args&&... args) &
+ constexpr void construct_unsafe(Args&&... args)
+ requires constructible_from<T, Args&&...>
{
- construct_at<T>(uninit_ptr(), ASL_FWD(args)...);
+ construct_at<T>(&m_value, ASL_FWD(args)...);
}
- // @Safety Must be called only when in initialized state.
- constexpr void uninit_unsafe() &
+ // @Safety Value must have been initialized
+ template<typename U>
+ constexpr void assign_unsafe(U&& value)
+ requires assignable_from<T&, U&&>
{
- destroy(init_ptr_unsafe());
+ m_value = ASL_FWD(value);
}
+
+ // @Safety Value must have been initialized
+ constexpr void destroy_unsafe()
+ {
+ if constexpr (!trivially_destructible<T>)
+ {
+ destroy(&m_value);
+ }
+ }
+
+ // @Safety Value must have been initialized
+ constexpr const T& as_init_unsafe() const& { return m_value; }
+ constexpr T& as_init_unsafe() & { return m_value; }
+ constexpr T&& as_init_unsafe() && { return ASL_MOVE(m_value); }
};
} // namespace asl