// Copyright 2025 Steven Le Rouzic // // SPDX-License-Identifier: BSD-3-Clause #pragma once #include "asl/base/meta.hpp" #include "asl/base/utility.hpp" #include "asl/memory/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 explicit constexpr maybe_uninit(in_place_t, auto&&... args) requires constructible_from : m_value{std::forward(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) { return *this; } // NOLINT constexpr maybe_uninit& operator=(maybe_uninit&&) requires trivially_move_assignable = default; constexpr maybe_uninit& operator=(maybe_uninit&&) requires (!trivially_move_assignable) { return *this; } // NOLINT constexpr ~maybe_uninit() requires trivially_destructible = default; constexpr ~maybe_uninit() requires (!trivially_destructible) {} // NOLINT // @Safety Value must not have been initialized yet constexpr void construct_unsafe(auto&&... args) requires constructible_from { construct_at(&m_value, std::forward(args)...); } // @Safety Value must have been initialized constexpr void assign_unsafe(auto&& value) requires assignable_from { m_value = std::forward(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 auto&& as_init_unsafe(this auto&& self) { return std::forward(self).m_value; } }; } // namespace asl