24#include "pw_assert/assert.h"
25#include "pw_containers/internal/optional_data.h"
27namespace pw::containers::internal {
34#define PW_OPTIONAL_STATE OptionalState
36#define PW_OPTIONAL_STATE
56 PW_OPTIONAL_STATE
auto kHasValueState,
57 bool IsTriviallyDestructible = std::is_trivially_destructible_v<T>>
59 decltype(kHasValueState),
61 IsTriviallyDestructible>,
62 private CopyCtorBase<T>,
63 private MoveCtorBase<T>,
64 private CopyAssignBase<T>,
65 private MoveAssignBase<T> {
67 template <
typename, PW_OPTIONAL_STATE auto,
bool>
70 using Base = OptionalData<T,
71 decltype(kHasValueState),
73 IsTriviallyDestructible>;
76 using state_type =
decltype(kHasValueState);
89 template <
typename... Args>
90 explicit constexpr Optional(std::in_place_t, Args&&... args)
91 : Base(std::in_place, std::forward<Args>(args)...) {}
101 std::enable_if_t<std::conjunction_v<std::negation<std::is_same<T, U>>,
102 std::is_constructible<T, const U&>,
103 std::is_convertible<const U&, T>>,
110 std::conjunction_v<std::negation<std::is_same<T, U>>,
111 std::is_constructible<T, const U&>,
112 std::negation<std::is_convertible<const U&, T>>>,
119 std::enable_if_t<std::conjunction_v<std::negation<std::is_same<T, U>>,
120 std::is_constructible<T, U&&>,
121 std::is_convertible<U&&, T>>,
123 constexpr Optional(Optional<U, kHasValueState>&& other)
124 : Base(std::move(other)) {}
126 template <
typename U,
128 std::conjunction_v<std::negation<std::is_same<T, U>>,
129 std::is_constructible<T, U&&>,
130 std::negation<std::is_convertible<U&&, T>>>,
132 explicit constexpr Optional(Optional<U, kHasValueState>&& other)
133 : Base(std::move(other)) {}
143 this->Assign(std::move(
value));
148 template <
typename... Args>
151 this->MakeValue(std::forward<Args>(args)...);
152 this->state_ = kHasValueState;
161 template <state_type kState>
163 this->
template AssignState<kState>();
168 return this->state_ == kHasValueState;
176 constexpr const T&
operator*() const& {
return this->data_; }
179 constexpr T&&
operator*() && {
return std::move(this->data_); }
181 constexpr const T&&
operator*() const&& {
return std::move(this->data_); }
186 constexpr const T*
operator->()
const {
return &this->data_; }
202 return std::move(this->data_);
205 constexpr const T&&
value() const&& {
207 return std::move(this->data_);
211 constexpr state_type
state()
const {
return this->state_; }
213 friend constexpr bool operator==(
const Optional& lhs,
const Optional& rhs) {
219 friend constexpr bool operator!=(
const Optional& lhs,
const Optional& rhs) {
220 return !(lhs == rhs);
223 friend constexpr bool operator==(
const Optional& lhs,
const T& rhs) {
224 return lhs.has_value() && *lhs == rhs;
226 friend constexpr bool operator==(
const T& lhs,
const Optional& rhs) {
229 friend constexpr bool operator!=(
const Optional& lhs,
const T& rhs) {
230 return !(lhs == rhs);
232 friend constexpr bool operator!=(
const T& lhs,
const Optional& rhs) {
233 return !(rhs == lhs);
236 static_assert(!std::is_convertible_v<T, state_type>,
237 "To avoid ambiguity, T cannot be convertible to the state "
238 "type. Consider using `enum class` to restrict conversions.");
239 static_assert(!std::is_convertible_v<state_type, T>,
240 "To avoid ambiguity, the state cannot be convertible to T "
241 "type. Consider using `enum class` to restrict conversions.");
246template <PW_OPTIONAL_STATE auto kHasValueState,
bool IsTriviallyDestructible>
249 using state_type =
decltype(kHasValueState);
250 using value_type = void;
261 explicit constexpr Optional(state_type state) : state_(state) {
262 PW_ASSERT(state != kHasValueState);
266 explicit constexpr Optional(std::in_place_t) : state_(kHasValueState) {}
269 constexpr void emplace() { state_ = kHasValueState; }
274 constexpr void reset(state_type state) {
275 PW_ASSERT(state != kHasValueState);
280 template <state_type kState>
283 kState != kHasValueState,
284 "Cannot set state to the has-value state; set the value instead");
290 return state_ == kHasValueState;
294 constexpr void value()
const { PW_ASSERT(has_value()); }
297 constexpr state_type
state()
const {
return state_; }
299 friend constexpr bool operator==(
const Optional& lhs,
const Optional& rhs) {
302 friend constexpr bool operator!=(
const Optional& lhs,
const Optional& rhs) {
303 return lhs.state() != rhs.state();
312#undef PW_OPTIONAL_STATE
constexpr Optional(std::in_place_t)
Constructs an optional containing a value.
Definition: optional.h:266
constexpr void reset()
Definition: optional.h:281
constexpr state_type state() const
Returns the underlying state value.
Definition: optional.h:297
constexpr void reset(state_type state)
Definition: optional.h:274
constexpr bool has_value() const
True if the optional contains a value.
Definition: optional.h:289
constexpr void emplace()
Sets the state to indicate a value is present.
Definition: optional.h:269
constexpr void value() const
Asserts that has_value() is true.
Definition: optional.h:294
constexpr Optional(state_type state)
Constructs an optional without a value using the provided state.
Definition: optional.h:261
Definition: optional.h:65
constexpr T && operator*() &&
Definition: optional.h:179
constexpr bool has_value() const
Returns true if the optional contains a value.
Definition: optional.h:167
constexpr T & operator*() &
Definition: optional.h:174
constexpr Optional & operator=(value_type &&value)
Move assigns a new value to the optional.
Definition: optional.h:142
constexpr T && value() &&
Returns the contained value. Asserts if the value is not present.
Definition: optional.h:200
constexpr const T * operator->() const
Definition: optional.h:186
constexpr void emplace(Args &&... args)
Constructs a new value in-place.
Definition: optional.h:149
constexpr Optional(state_type state)
Constructs an optional without a value using the provided state.
Definition: optional.h:82
constexpr state_type state() const
Returns the state. Always valid, whether has_value is true or false.
Definition: optional.h:211
constexpr Optional(std::in_place_t, Args &&... args)
Constructs an optional in-place containing a value.
Definition: optional.h:90
constexpr void reset(state_type state)
Definition: optional.h:158
constexpr void reset()
Definition: optional.h:162
constexpr const T && value() const &&
Returns the contained value. Asserts if the value is not present.
Definition: optional.h:205
constexpr Optional(const value_type &value)
Constructs an optional containing a value.
Definition: optional.h:85
constexpr T & value() &
Returns the contained value. Asserts if the value is not present.
Definition: optional.h:189
constexpr Optional(const Optional< U, kHasValueState > &other)
Constructs an optional from another optional with a compatible value type.
Definition: optional.h:105
constexpr Optional & operator=(const value_type &value)
Assigns a new value to the optional.
Definition: optional.h:136
constexpr const T && operator*() const &&
Definition: optional.h:181
constexpr const T & operator*() const &
Definition: optional.h:176
constexpr T * operator->()
Definition: optional.h:184
constexpr const T & value() const &
Returns the contained value. Asserts if the value is not present.
Definition: optional.h:194
Definition: optional.h:33