4#ifndef TETL_OPTIONAL_OPTIONAL_HPP
5#define TETL_OPTIONAL_OPTIONAL_HPP
7#include <etl/_config/all.hpp>
9#include <etl/_concepts/copy_constructible.hpp>
10#include <etl/_concepts/move_constructible.hpp>
11#include <etl/_concepts/same_as.hpp>
12#include <etl/_contracts/check.hpp>
13#include <etl/_functional/hash.hpp>
14#include <etl/_functional/invoke.hpp>
15#include <etl/_iterator/next.hpp>
16#include <etl/_memory/addressof.hpp>
17#include <etl/_optional/nullopt.hpp>
18#include <etl/_type_traits/add_lvalue_reference.hpp>
19#include <etl/_type_traits/conjunction.hpp>
20#include <etl/_type_traits/decay.hpp>
21#include <etl/_type_traits/invoke_result.hpp>
22#include <etl/_type_traits/is_assignable.hpp>
23#include <etl/_type_traits/is_constructible.hpp>
24#include <etl/_type_traits/is_convertible.hpp>
25#include <etl/_type_traits/is_lvalue_reference.hpp>
26#include <etl/_type_traits/is_nothrow_move_constructible.hpp>
27#include <etl/_type_traits/is_nothrow_swappable.hpp>
28#include <etl/_type_traits/is_same.hpp>
29#include <etl/_type_traits/is_scalar.hpp>
30#include <etl/_type_traits/is_specialized.hpp>
31#include <etl/_type_traits/remove_const.hpp>
32#include <etl/_type_traits/remove_cv.hpp>
33#include <etl/_type_traits/remove_cvref.hpp>
34#include <etl/_utility/forward.hpp>
35#include <etl/_utility/in_place.hpp>
36#include <etl/_utility/in_place_index.hpp>
37#include <etl/_utility/move.hpp>
38#include <etl/_utility/swap.hpp>
39#include <etl/_variant/monostate.hpp>
40#include <etl/_variant/variant.hpp>
94 using const_iterator = T
const*;
96 static_assert(!is_array_v<T>,
"instantiation of optional with an array type is ill-formed");
97 static_assert(!is_same_v<remove_cvref_t<T>,
nullopt_t>,
"instantiation of optional with nullopt_t is ill-formed");
98 static_assert(!is_same_v<remove_cvref_t<T>,
in_place_t>,
"instantiation of optional with in_place_t is ill-formed");
121 template <
typename U>
123 is_constructible_v<T, U
const&>
124 and not is_same_v<remove_cv_t<U>,
bool>
125 and not is_constructible_v<T,
optional<U>&>
126 and not is_constructible_v<T,
optional<U>
const&>
127 and not is_constructible_v<T,
optional<U> &&>
128 and not is_constructible_v<T,
optional<U>
const &&>
129 and not is_convertible_v<
optional<U>&, T>
130 and not is_convertible_v<
optional<U>
const&, T>
131 and not is_convertible_v<
optional<U> &&, T>
132 and not is_convertible_v<
optional<U>
const &&, T>
137 if (other.has_value()) {
150 template <
typename U>
152 is_constructible_v<T, U &&>
153 and not is_same_v<remove_cv_t<U>,
bool>
154 and not is_constructible_v<T,
optional<U>&>
155 and not is_constructible_v<T,
optional<U>
const&>
156 and not is_constructible_v<T,
optional<U> &&>
157 and not is_constructible_v<T,
optional<U>
const &&>
158 and not is_convertible_v<
optional<U>&, T>
159 and not is_convertible_v<
optional<U>
const&, T>
160 and not is_convertible_v<
optional<U> &&, T>
161 and not is_convertible_v<
optional<U>
const &&, T>
165 if (other.has_value()) {
166 emplace(*
etl::move(other));
174 template <
typename... Args>
175 requires is_constructible_v<T, Args...>
177 : _var(in_place_index<1>,
etl::forward<Args>(args)...)
185 template <
typename U = T>
187 is_constructible_v<T, U &&>
188 and not is_same_v<remove_cvref_t<U>,
in_place_t>
189 and not is_same_v<remove_cvref_t<U>,
optional>
192 : _var(in_place_index<1>,
etl::forward<U>(value))
218 template <
typename U = T>
220 is_assignable_v<T&, U>
221 and is_constructible_v<T, U>
222 and not is_same_v<
optional, decay_t<U>>
223 and not is_scalar_v<T>
224 and not is_same_v<T, decay_t<U>>
228 emplace(
etl::forward<U>(value));
233 template <
typename U = T>
235 is_constructible_v<T, U
const&>
236 and is_assignable_v<T&, U
const&>
237 and not is_constructible_v<T,
optional<U>&>
238 and not is_constructible_v<T,
optional<U>
const&>
239 and not is_constructible_v<T,
optional<U> &&>
240 and not is_constructible_v<T,
optional<U>
const &&>
241 and not is_convertible_v<
optional<U>&, T>
242 and not is_convertible_v<
optional<U>
const&, T>
243 and not is_convertible_v<
optional<U> &&, T>
244 and not is_convertible_v<
optional<U>
const &&, T>
245 and not is_assignable_v<T&,
optional<U>&>
246 and not is_assignable_v<T&,
optional<U>
const&>
247 and not is_assignable_v<T&,
optional<U> &&>
248 and not is_assignable_v<T&,
optional<U>
const &&>
252 if (other.has_value()) {
262 template <
typename U = T>
264 is_constructible_v<T, U>
265 and is_assignable_v<T&, U>
266 and not is_constructible_v<T,
optional<U>&>
267 and not is_constructible_v<T,
optional<U>
const&>
268 and not is_constructible_v<T,
optional<U> &&>
269 and not is_constructible_v<T,
optional<U>
const &&>
270 and not is_convertible_v<
optional<U>&, T>
271 and not is_convertible_v<
optional<U>
const&, T>
272 and not is_convertible_v<
optional<U> &&, T>
273 and not is_convertible_v<
optional<U>
const &&, T>
274 and not is_assignable_v<T&,
optional<U>&>
275 and not is_assignable_v<T&,
optional<U>
const&>
276 and not is_assignable_v<T&,
optional<U> &&>
277 and not is_assignable_v<T&,
optional<U>
const &&>
281 if (other.has_value()) {
282 emplace(*
etl::move(other));
293 return _var.index() == 1;
305 constexpr auto reset()
noexcept ->
void
307 _var.
template emplace<0>(
nullopt);
312 template <
typename U>
313 [[nodiscard]]
constexpr auto value_or(U&& defaultValue)
const& -> value_type
315 return has_value() ? (**
this) :
static_cast<value_type>(
etl::forward<U>(defaultValue));
320 template <
typename U>
321 [[nodiscard]]
constexpr auto value_or(U&& defaultValue) && -> value_type
323 return has_value() ?
etl::move(**
this) :
static_cast<value_type>(
etl::forward<U>(defaultValue));
330 return etl::get_if<1>(&_var);
337 return etl::get_if<1>(&_var);
350 TETL_PRECONDITION(has_value());
351 return etl::unchecked_get<1>(_var);
364 TETL_PRECONDITION(has_value());
365 return etl::unchecked_get<1>(_var);
378 TETL_PRECONDITION(has_value());
379 return etl::move(
etl::unchecked_get<1>(_var));
392 TETL_PRECONDITION(has_value());
393 return etl::move(
etl::unchecked_get<1>(_var));
421 etl::swap(*
this, other);
427 template <
typename... Args>
428 constexpr auto emplace(Args&&... args) -> value_type&
430 return _var.
template emplace<1>(
etl::forward<Args>(args)...);
433 template <
typename F>
437 return etl::invoke(
etl::forward<F>(f), **
this);
439 return remove_cvref_t<invoke_result_t<F, T&>>{};
442 template <
typename F>
446 return etl::invoke(
etl::forward<F>(f), **
this);
448 return remove_cvref_t<invoke_result_t<F, T
const&>>{};
451 template <
typename F>
455 return etl::invoke(
etl::forward<F>(f),
etl::move(**
this));
457 return remove_cvref_t<invoke_result_t<F, T>>{};
460 template <
typename F>
464 return etl::invoke(
etl::forward<F>(f),
etl::move(**
this));
466 return remove_cvref_t<invoke_result_t<F, T
const>>{};
469 template <
typename F>
470 requires(copy_constructible<T>
and same_as<remove_cvref_t<invoke_result_t<F>>,
optional>)
473 return *
this ? *
this :
etl::forward<F>(f)();
476 template <
typename F>
477 requires(move_constructible<T>
and same_as<remove_cvref_t<invoke_result_t<F>>,
optional>)
480 return *
this ?
etl::move(*
this) :
etl::forward<F>(f)();
490 using value_type = T&;
499 template <
typename U = T>
500 requires(
not is_same_v<remove_cvref_t<U>,
optional>)
502 : _ptr(
etl::addressof(v))
504 static_assert(is_constructible_v<add_lvalue_reference_t<T>, U>,
"Must be able to bind U to T&");
505 static_assert(is_lvalue_reference_v<U>,
"U must be an lvalue");
508 template <
typename U>
509 requires(
not is_same_v<remove_cvref_t<U>,
optional>)
511 : _ptr(
etl::addressof(*rhs))
528 template <
typename U = T>
529 requires(
not is_same_v<remove_cvref_t<U>,
optional>
and not conjunction_v<is_scalar<T>,
is_same<T, decay_t<U>>>)
532 static_assert(is_constructible_v<add_lvalue_reference_t<T>, U>,
"Must be able to bind U to T&");
533 static_assert(is_lvalue_reference_v<U>,
"U must be an lvalue");
534 _ptr =
etl::addressof(v);
538 template <
typename U>
541 static_assert(is_constructible_v<add_lvalue_reference_t<T>, U>,
"Must be able to bind U to T&");
546 template <
typename U = T>
547 requires(
not is_same_v<remove_cvref_t<U>,
optional>)
550 *
this =
etl::forward<U>(u);
561 TETL_PRECONDITION(has_value());
572 return _ptr !=
nullptr;
582 etl::swap(_ptr, rhs._ptr);
601template <
typename T,
typename... Args>
618template <
typename T,
typename U>
621 if (
static_cast<
bool>(lhs) !=
static_cast<
bool>(rhs)) {
624 if (
not static_cast<
bool>(lhs)
and not static_cast<
bool>(rhs)) {
627 return (*lhs) == (*rhs);
633template <
typename T,
typename U>
636 if (
not static_cast<
bool>(rhs)) {
639 if (
not static_cast<
bool>(lhs)) {
642 return (*lhs) < (*rhs);
648template <
typename T,
typename U>
651 if (
not static_cast<
bool>(lhs)) {
654 if (
not static_cast<
bool>(rhs)) {
657 return (*lhs) > (*rhs);
663template <
typename T,
typename U>
666 if (
not static_cast<
bool>(lhs)) {
669 if (
not static_cast<
bool>(rhs)) {
672 return (*lhs) <= (*rhs);
678template <
typename T,
typename U>
681 if (
not static_cast<
bool>(rhs)) {
684 if (
not static_cast<
bool>(lhs)) {
687 return (*lhs) >= (*rhs);
735 return static_cast<
bool>(opt);
748template <
typename T,
typename U>
751 return static_cast<
bool>(opt) ? *opt == value :
false;
764template <
typename T,
typename U>
767 return static_cast<
bool>(opt) ? *opt < value :
true;
780template <
typename T,
typename U>
783 return static_cast<
bool>(opt) ? value < *opt :
false;
796template <
typename T,
typename U>
799 return static_cast<
bool>(opt) ? *opt > value :
false;
812template <
typename T,
typename U>
815 return static_cast<
bool>(opt) ? value > *opt :
true;
828template <
typename T,
typename U>
831 return static_cast<
bool>(opt) ? *opt <= value :
true;
844template <
typename T,
typename U>
847 return static_cast<
bool>(opt) ? value <= *opt :
false;
860template <
typename T,
typename U>
863 return static_cast<
bool>(opt) ? *opt >= value :
false;
876template <
typename T,
typename U>
879 return static_cast<
bool>(opt) ? value >= *opt :
true;
904 using type =
etl::remove_const_t<T>;
905 static_assert(
etl::is_specialized_v<
etl::hash, type>);
906 return static_cast<
bool>(opt) ?
etl::hash<type>{}(*opt) : 0;
constexpr auto operator>=(optional< T > const &opt, U const &value) -> bool
Compares opt with a value. The values are compared (using the corresponding operator of T) only if op...
Definition optional.hpp:861
constexpr auto operator==(optional< T > const &opt, U const &value) -> bool
Compares opt with a value. The values are compared (using the corresponding operator of T) only if op...
Definition optional.hpp:749
constexpr auto operator>(optional< T > const &lhs, optional< U > const &rhs) -> bool
Compares two optional objects, lhs and rhs.
Definition optional.hpp:649
optional(T) -> optional< T >
constexpr auto operator>(optional< T > const &opt, U const &value) -> bool
Compares opt with a value. The values are compared (using the corresponding operator of T) only if op...
Definition optional.hpp:797
constexpr auto operator==(etl::nullopt_t, optional< T > const &opt) noexcept -> bool
Compares opt with a nullopt.
Definition optional.hpp:709
constexpr auto operator<=(T const &value, optional< U > const &opt) -> bool
Compares opt with a value. The values are compared (using the corresponding operator of T) only if op...
Definition optional.hpp:845
constexpr auto make_optional(Args &&... args) -> etl::optional< T >
Creates an optional object constructed in-place from args...
Definition optional.hpp:602
constexpr auto operator<=(optional< T > const &opt, U const &value) -> bool
Compares opt with a value. The values are compared (using the corresponding operator of T) only if op...
Definition optional.hpp:829
constexpr auto operator>=(optional< T > const &lhs, optional< U > const &rhs) -> bool
Compares two optional objects, lhs and rhs.
Definition optional.hpp:679
constexpr auto operator<=(optional< T > const &lhs, optional< U > const &rhs) -> bool
Compares two optional objects, lhs and rhs.
Definition optional.hpp:664
constexpr auto operator>=(T const &value, optional< U > const &opt) -> bool
Compares opt with a value. The values are compared (using the corresponding operator of T) only if op...
Definition optional.hpp:877
constexpr auto operator<(T const &value, optional< U > const &opt) -> bool
Compares opt with a value. The values are compared (using the corresponding operator of T) only if op...
Definition optional.hpp:781
constexpr auto operator<(optional< T > const &, etl::nullopt_t) noexcept -> bool
Compares opt with a nullopt.
Definition optional.hpp:721
constexpr auto operator==(optional< T > const &lhs, optional< U > const &rhs) -> bool
Compares two optional objects, lhs and rhs.
Definition optional.hpp:619
constexpr auto operator<(optional< T > const &opt, U const &value) -> bool
Compares opt with a value. The values are compared (using the corresponding operator of T) only if op...
Definition optional.hpp:765
constexpr auto operator<(optional< T > const &lhs, optional< U > const &rhs) -> bool
Compares two optional objects, lhs and rhs.
Definition optional.hpp:634
constexpr auto make_optional(T &&value) -> etl::optional< etl::decay_t< T > >
Creates an optional object from value.
Definition optional.hpp:593
constexpr auto operator<(etl::nullopt_t, optional< T > const &opt) noexcept -> bool
Compares opt with a nullopt.
Definition optional.hpp:733
constexpr auto nullopt
etl::nullopt is a constant of type etl::nullopt_t that is used to indicate optional type with uniniti...
Definition nullopt.hpp:22
constexpr auto operator==(optional< T > const &opt, etl::nullopt_t) noexcept -> bool
Compares opt with a nullopt.
Definition optional.hpp:697
constexpr auto operator>(T const &value, optional< U > const &opt) -> bool
Compares opt with a value. The values are compared (using the corresponding operator of T) only if op...
Definition optional.hpp:813
Definition adjacent_find.hpp:9
constexpr auto operator()(etl::optional< T > const &opt) const -> etl::size_t
Definition optional.hpp:902
Disambiguation tags that can be passed to the constructors of optional, variant, and any to indicate ...
Definition in_place.hpp:21
constexpr auto in_place
Definition in_place.hpp:26
If T and U name the same type (taking into account const/volatile qualifications),...
Definition is_same.hpp:16
etl::nullopt_t is an empty class type used to indicate optional type with uninitialized state....
Definition nullopt.hpp:14
constexpr auto emplace(U &&u) noexcept -> optional &
Definition optional.hpp:548
constexpr optional(optional &&other) noexcept=default
constexpr void swap(optional &rhs) noexcept
Definition optional.hpp:580
constexpr optional() noexcept=default
constexpr auto operator=(U &&v) -> optional &
Definition optional.hpp:530
constexpr auto operator=(nullopt_t) noexcept -> optional &
Definition optional.hpp:522
constexpr operator bool() const noexcept
Definition optional.hpp:565
constexpr explicit(not is_convertible_v< U, T >) optional(optional< U > const &rhs)
Definition optional.hpp:510
constexpr auto operator=(optional &&) noexcept -> optional &=default
constexpr optional(optional const &other)=default
constexpr explicit(not is_convertible_v< U, T >) optional(U &&v)
Definition optional.hpp:501
constexpr auto operator=(optional const &) noexcept -> optional &=default
constexpr ~optional()=default
constexpr void reset() noexcept
Definition optional.hpp:575
constexpr auto operator=(optional< U > const &rhs) -> optional &
Definition optional.hpp:539
constexpr auto operator->() const noexcept -> T *
Definition optional.hpp:554
constexpr auto has_value() const noexcept -> bool
Definition optional.hpp:570
constexpr auto operator*() const noexcept -> T &
Definition optional.hpp:559
constexpr optional(nullopt_t) noexcept
Definition optional.hpp:494
The class template optional manages an optional contained value, i.e. a value that may or may not be ...
Definition optional.hpp:91
constexpr auto operator=(optional< U > &&other) -> optional &
Assigns the state of other.
Definition optional.hpp:279
constexpr auto value_or(U &&defaultValue) &&-> value_type
Returns the contained value if *this has a value, otherwise returns default_value.
Definition optional.hpp:321
constexpr auto operator=(optional const &other) -> optional &=default
Assigns the state of other.
constexpr auto and_then(F &&f) &&
Definition optional.hpp:452
constexpr auto operator=(optional< U > const &other) -> optional &
Assigns the state of other.
Definition optional.hpp:250
constexpr auto or_else(F &&f) const &-> optional
Definition optional.hpp:471
constexpr auto or_else(F &&f) &&-> optional
Definition optional.hpp:478
constexpr optional(in_place_t, Args &&... args)
Constructs an optional object that contains a value, initialized as if direct-initializing.
Definition optional.hpp:176
constexpr auto reset() noexcept -> void
If *this contains a value, destroy that value as if by value().~value_type(). Otherwise,...
Definition optional.hpp:305
constexpr auto operator=(optional &&other) noexcept -> optional &=default
Assigns the state of other.
constexpr auto operator*() const &-> T const &
Returns a reference to the contained value.
Definition optional.hpp:348
constexpr auto and_then(F &&f) &
Definition optional.hpp:434
constexpr optional() noexcept=default
Constructs an object that does not contain a value.
constexpr auto swap(optional &other) noexcept(is_nothrow_move_constructible_v< value_type > and is_nothrow_swappable_v< value_type >) -> void
Swaps the contents with those of other.
Definition optional.hpp:418
constexpr auto begin() noexcept -> iterator
Definition optional.hpp:396
explicit(not is_convertible_v< U &&, T >) const expr optional(optional< U > &&other)
Converting move constructor.
Definition optional.hpp:163
constexpr operator bool() const noexcept
Checks whether *this contains a value.
Definition optional.hpp:297
constexpr auto end() noexcept -> iterator
Definition optional.hpp:406
constexpr auto begin() const noexcept -> const_iterator
Definition optional.hpp:401
explicit(not is_convertible_v< U const &, T >) const expr optional(optional< U > const &other)
Converting copy constructor.
Definition optional.hpp:135
constexpr auto operator=(etl::nullopt_t) noexcept -> optional &
If *this contains a value before the call, the contained value is destroyed by calling its destructor...
Definition optional.hpp:199
constexpr optional(optional &&) noexcept(is_nothrow_move_constructible_v< value_type >)=default
Move constructor.
constexpr auto end() const noexcept -> const_iterator
Definition optional.hpp:411
constexpr auto value_or(U &&defaultValue) const &-> value_type
Returns the contained value if *this has a value, otherwise returns default_value.
Definition optional.hpp:313
constexpr optional(optional const &)=default
Copy constructor.
constexpr auto operator*() &-> T &
Returns a reference to the contained value.
Definition optional.hpp:362
constexpr auto operator->() -> value_type *
Returns a pointer to the contained value. The pointer is null if the optional is empty.
Definition optional.hpp:335
constexpr auto has_value() const noexcept -> bool
Checks whether *this contains a value.
Definition optional.hpp:291
constexpr auto and_then(F &&f) const &&
Definition optional.hpp:461
constexpr auto and_then(F &&f) const &
Definition optional.hpp:443
constexpr auto operator*() const &&-> T const &&
Returns a reference to the contained value.
Definition optional.hpp:376
constexpr auto operator->() const -> value_type const *
Returns a pointer to the contained value. The pointer is null if the optional is empty.
Definition optional.hpp:328
constexpr auto operator*() &&-> T &&
Returns a reference to the contained value.
Definition optional.hpp:390
explicit(not is_convertible_v< U &&, T >) const expr optional(U &&value)
Constructs an optional object that contains a value, initialized as if direct-initializing.
Definition optional.hpp:191
constexpr auto emplace(Args &&... args) -> value_type &
Constructs the contained value in-place. If *this already contains a value before the call,...
Definition optional.hpp:428
constexpr optional(nullopt_t) noexcept
Constructs an object that does not contain a value.
Definition optional.hpp:104
constexpr auto operator=(U &&value) -> optional &
Perfect-forwarded assignment.
Definition optional.hpp:226
Definition variant.hpp:99