9#include "../../assert.hpp"
24 static_assert(!std::is_reference_v<T>,
25 "yorch::detail::maybe_storage<T> does not support reference types");
26 static_assert(!std::is_void_v<T>,
27 "yorch::detail::maybe_storage<T> requires a non-void type");
36 if (
other.has_value()) {
42 requires (!std::copy_constructible<T>)
47 noexcept(std::is_nothrow_move_constructible_v<T>)
48 requires std::move_constructible<T>
50 if (
other.has_value()) {
56 requires (!std::move_constructible<T>)
61 requires std::copy_constructible<T>
72 requires (!std::copy_constructible<T>)
78 requires std::move_constructible<T>
84 assign_from(std::move(
other));
89 requires (!std::move_constructible<T>)
96 template <
typename...
Args>
98 noexcept(std::is_nothrow_constructible_v<
T,
Args&&...>)
101 "yorch::detail::maybe_storage<T>::emplace() called on a live value");
103 auto*
object = std::construct_at(ptr(), std::forward<Args>(
args)...);
113 std::destroy_at(ptr());
123 "yorch::detail::maybe_storage<T>::get() called on an empty value");
129 "yorch::detail::maybe_storage<T>::get() called on an empty value");
135 "yorch::detail::maybe_storage<T>::get() called on an empty value");
136 return std::move(*ptr());
156 template <
typename Storage>
157 using storage_value_t =
decltype(std::declval<Storage>().get());
159 template <
typename Storage>
160 static constexpr bool assign_from_nothrow_v =
161 std::is_nothrow_destructible_v<T> &&
162 std::is_nothrow_constructible_v<T, storage_value_t<Storage>> &&
163 (!std::is_assignable_v<T&, storage_value_t<Storage>> ||
164 std::is_nothrow_assignable_v<T&, storage_value_t<Storage>>);
166 template <
typename Storage>
168 if (
other.has_value()) {
170 if constexpr (std::is_assignable_v<T&, decltype(std::forward<Storage>(
other).get())>) {
171 get() = std::forward<Storage>(
other).get();
185 return std::launder(
reinterpret_cast<T*
>(storage_));
189 return std::launder(
reinterpret_cast<const T*
>(storage_));
193 alignas(
T) std::byte storage_[
sizeof(
T)] {};
194 bool engaged_ =
false;
#define YORCH_ASSERT(condition)
constexpr bool is_adapter_descriptor_v
Manual-lifetime storage for an optional in-place T.
constexpr T & get() &noexcept
constexpr maybe_storage(maybe_storage &&other) noexcept(std::is_nothrow_move_constructible_v< T >)
constexpr void destroy() noexcept
constexpr T & emplace(Args &&... args) noexcept(std::is_nothrow_constructible_v< T, Args &&... >)
constexpr T * raw_ptr() noexcept
constexpr maybe_storage & operator=(maybe_storage &&other) noexcept(assign_from_nothrow_v< maybe_storage && >)
constexpr bool has_value() const noexcept
constexpr maybe_storage & operator=(maybe_storage &&)=delete
constexpr maybe_storage() noexcept=default
constexpr maybe_storage(const maybe_storage &)=delete
constexpr const T * raw_ptr() const noexcept
constexpr const T & get() const &noexcept
constexpr bool * engaged_ptr() noexcept
constexpr T && get() &&noexcept
constexpr maybe_storage(maybe_storage &&)=delete
constexpr maybe_storage & operator=(const maybe_storage &)=delete
constexpr maybe_storage & operator=(const maybe_storage &other) noexcept(assign_from_nothrow_v< const maybe_storage & >)
constexpr const bool * engaged_ptr() const noexcept