13 template <
typename T, T
SENTINEL = T{}>
14 struct sentinel_optional
16 constexpr sentinel_optional()
noexcept {}
17 constexpr sentinel_optional(std::nullopt_t)
noexcept {}
19 template <
class...
TYPES, std::enable_if_t<std::is_constructible_v<T,
TYPES...>,
int> = 0>
20 constexpr explicit sentinel_optional(std::in_place_t,
TYPES&&...
args)
noexcept(std::is_nothrow_constructible_v<T,
TYPES...>)
25 template <
class U = T, std::enable_if_t<
26 !std::is_same_v<remove_cvref_t<U>, sentinel_optional> &&
27 !std::is_same_v<remove_cvref_t<U>, std::in_place_t> &&
28 !std::is_same_v<std::remove_cv_t<U>,
bool> &&
29 std::is_constructible_v<T, U>
31 constexpr sentinel_optional(
U&&
right)
noexcept(std::is_nothrow_constructible_v<T, U>)
32 : m_value(std::forward<
U>(
right))
36 template <
class U, std::enable_if_t<std::is_constructible_v<T, const U&>,
int> = 0>
37 constexpr explicit sentinel_optional(
const sentinel_optional<U>&
right)
noexcept(std::is_nothrow_constructible_v<T, const U&>)
40 this->m_value = *
right;
43 template <
class U, std::enable_if_t<std::is_constructible_v<T, U>,
int> = 0>
47 this->m_value = std::move(*
right);
50 constexpr sentinel_optional& operator=(std::nullopt_t)
noexcept {
55 template <
class U = T, std::enable_if_t<
56 !std::is_same_v<sentinel_optional, remove_cvref_t<U>> &&
57 std::is_constructible_v<T, U> &&
58 std::is_assignable_v<T&, U>,
60 constexpr sentinel_optional& operator=(
U&&
right)
noexcept(std::is_nothrow_assignable_v<T&, U> && std::is_nothrow_constructible_v<T, U>)
62 this->m_value = std::forward<U>(
right);
66 template <
class U, std::enable_if_t<
68 std::is_same_v<T, U> ||
69 std::is_assignable_v<T&, sentinel_optional<U>&> ||
70 std::is_assignable_v<T&, const sentinel_optional<U>&> ||
71 std::is_assignable_v<T&, const sentinel_optional<U>> ||
72 std::is_assignable_v<T&, sentinel_optional<U>>
74 std::is_constructible_v<T, const U&> &&
75 std::is_assignable_v<T&, const U&>,
77 constexpr sentinel_optional&
operator=(
const sentinel_optional<U>&
right)
noexcept(std::is_nothrow_assignable_v<T&, const U&> && std::is_nothrow_constructible_v<T, const U&>)
80 this->m_value = *
right;
87 template <
class U, std::enable_if_t<
89 std::is_same_v<T, U> ||
90 std::is_assignable_v<T&, sentinel_optional<U>&> ||
91 std::is_assignable_v<T&, const sentinel_optional<U>&> ||
92 std::is_assignable_v<T&, const sentinel_optional<U>> ||
93 std::is_assignable_v<T&, sentinel_optional<U>>
95 std::is_constructible_v<T, U> &&
96 std::is_assignable_v<T&, U>,
98 constexpr sentinel_optional&
operator=(
sentinel_optional<U>&&
right)
noexcept(std::is_nothrow_assignable_v<T&, U>&& std::is_nothrow_constructible_v<T, U>)
101 this->m_value = std::move(*
right);
108 template <
class...
TYPES>
109 constexpr T& emplace(
TYPES&&...
args)
noexcept(std::is_nothrow_constructible_v<T,
TYPES...>)
112 return this->m_value = T(std::forward<TYPES>(
args)...);
115 inline constexpr void assert_value()
const {
if (this->m_value ==
SENTINEL)
throw std::bad_optional_access(); }
117 [[
nodiscard]]
constexpr const T* operator->()
const
119 this->assert_value();
120 return std::addressof(this->m_value);
124 this->assert_value();
125 return std::addressof(this->m_value);
130 this->assert_value();
131 return this->m_value;
136 this->assert_value();
137 return this->m_value;
140 [[
nodiscard]]
constexpr T&& operator*() &&
142 this->assert_value();
143 return std::move(this->m_value);
148 this->assert_value();
149 return std::move(this->m_value);
156 this->assert_value();
157 return this->m_value;
160 this->assert_value();
161 return this->m_value;
164 this->assert_value();
165 return std::move(this->m_value);
168 this->assert_value();
169 return std::move(this->m_value);
173 return this->m_value;
175 [[
nodiscard]]
constexpr T& raw_value() & {
176 return this->m_value;
178 [[
nodiscard]]
constexpr T&& raw_value() && {
179 return std::move(this->m_value);
182 return std::move(this->m_value);
218 [[
nodiscard]]
constexpr bool operator==(
const sentinel_optional&
other)
const {
return this->m_value ==
other.m_value; }
219 [[
nodiscard]]
constexpr bool operator!=(
const sentinel_optional&
other)
const {
return this->m_value !=
other.m_value; }
220 [[
nodiscard]]
constexpr bool operator>=(
const sentinel_optional&
other)
const {
return this->m_value >=
other.m_value; }
221 [[
nodiscard]]
constexpr bool operator>(
const sentinel_optional&
other)
const {
return this->m_value >
other.m_value; }
222 [[
nodiscard]]
constexpr bool operator<=(
const sentinel_optional&
other)
const {
return this->m_value <=
other.m_value; }
223 [[
nodiscard]]
constexpr bool operator<(
const sentinel_optional&
other)
const {
return this->m_value <
other.m_value; }
233 template <
class T, std::enable_if_t<std::is_constructible_v<std::decay_t<T>, T>,
int> = 0>
238 template <
class T,
class...
TYPES, std::enable_if_t<std::is_constructible_v<T,
TYPES...>,
int> = 0>
constexpr auto bit_count
Equal to the number of bits in the type.
Primary namespace for everything in this library.