#pragma once #include "asl/meta.hpp" #include "asl/utility.hpp" #include "asl/memory.hpp" namespace asl { template union maybe_uninit { private: T m_value; public: constexpr maybe_uninit() requires trivially_default_constructible = default; constexpr maybe_uninit() requires (!trivially_default_constructible) {} // NOLINT template explicit constexpr maybe_uninit(in_place_t, Args&&... args) requires constructible_from : m_value{ASL_FWD(args)...} {} constexpr maybe_uninit(const maybe_uninit&) requires trivially_copy_constructible = default; constexpr maybe_uninit(const maybe_uninit&) requires (!trivially_copy_constructible) {} // NOLINT constexpr maybe_uninit(maybe_uninit&&) requires trivially_move_constructible = default; constexpr maybe_uninit(maybe_uninit&&) requires (!trivially_move_constructible) {} // NOLINT constexpr maybe_uninit& operator=(const maybe_uninit&) requires trivially_copy_assignable = default; constexpr maybe_uninit& operator=(const maybe_uninit&) requires (!trivially_copy_assignable) {} constexpr maybe_uninit& operator=(maybe_uninit&&) requires trivially_move_assignable = default; constexpr maybe_uninit& operator=(maybe_uninit&&) requires (!trivially_move_assignable) {} constexpr ~maybe_uninit() requires trivially_destructible = default; constexpr ~maybe_uninit() requires (!trivially_destructible) {} // NOLINT // @Safety Value must not have been initialized yet template constexpr void construct_unsafe(Args&&... args) requires constructible_from { construct_at(&m_value, ASL_FWD(args)...); } // @Safety Value must have been initialized template constexpr void assign_unsafe(U&& value) requires assignable_from { m_value = ASL_FWD(value); } // @Safety Value must have been initialized constexpr void destroy_unsafe() { if constexpr (!trivially_destructible) { 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