1 //===-- Standalone implementation of std::optional --------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIBC_SRC_SUPPORT_CPP_OPTIONAL_H
10 #define LLVM_LIBC_SRC_SUPPORT_CPP_OPTIONAL_H
12 #include "src/__support/CPP/type_traits.h"
13 #include "src/__support/CPP/utility.h"
14 #include "src/__support/macros/attributes.h"
16 namespace __llvm_libc
{
19 // Trivial in_place_t struct.
21 LIBC_INLINE_VAR
explicit in_place_t() = default;
24 // Trivial nullopt_t struct.
26 LIBC_INLINE_VAR
explicit nullopt_t() = default;
29 // nullopt that can be used and returned.
30 LIBC_INLINE_VAR
constexpr nullopt_t nullopt
{};
32 // in_place that can be used in the constructor.
33 LIBC_INLINE_VAR
constexpr in_place_t in_place
{};
35 // This is very simple implementation of the std::optional class. It makes
36 // several assumptions that the underlying type is trivially constructable,
37 // copyable, or movable.
38 template <typename T
> class optional
{
39 template <typename U
> class OptionalStorage
{
47 LIBC_INLINE
~OptionalStorage() { reset(); }
49 LIBC_INLINE
constexpr OptionalStorage() : empty(), in_use(false) {}
51 template <typename
... Args
>
52 LIBC_INLINE
constexpr explicit OptionalStorage(in_place_t
, Args
&&...args
)
53 : stored_value(forward
<Args
>(args
)...), in_use(true) {}
55 LIBC_INLINE
void reset() {
61 LIBC_INLINE
constexpr bool has_value() const { return in_use
; }
63 LIBC_INLINE U
&value() & { return stored_value
; }
64 LIBC_INLINE
constexpr U
const &value() const & { return stored_value
; }
65 LIBC_INLINE U
&&value() && { return move(stored_value
); }
68 OptionalStorage
<T
> storage
;
71 LIBC_INLINE
constexpr optional() = default;
72 LIBC_INLINE
constexpr optional(nullopt_t
) {}
74 LIBC_INLINE
constexpr optional(const T
&t
) : storage(in_place
, t
) {}
75 LIBC_INLINE
constexpr optional(const optional
&) = default;
77 LIBC_INLINE
constexpr optional(T
&&t
) : storage(in_place
, move(t
)) {}
78 LIBC_INLINE
constexpr optional(optional
&&O
) = default;
80 template <typename
... ArgTypes
>
81 LIBC_INLINE
constexpr optional(in_place_t
, ArgTypes
&&...Args
)
82 : storage(in_place
, forward
<ArgTypes
>(Args
)...) {}
84 LIBC_INLINE optional
&operator=(T
&&t
) {
88 LIBC_INLINE optional
&operator=(optional
&&) = default;
90 LIBC_INLINE
static constexpr optional
create(const T
*t
) {
91 return t
? optional(*t
) : optional();
94 LIBC_INLINE optional
&operator=(const T
&t
) {
98 LIBC_INLINE optional
&operator=(const optional
&) = default;
100 LIBC_INLINE
void reset() { storage
.reset(); }
102 LIBC_INLINE
constexpr const T
&value() const & { return storage
.value(); }
103 LIBC_INLINE T
&value() & { return storage
.value(); }
105 LIBC_INLINE
constexpr explicit operator bool() const { return has_value(); }
106 LIBC_INLINE
constexpr bool has_value() const { return storage
.has_value(); }
107 LIBC_INLINE
constexpr const T
*operator->() const { return &storage
.value(); }
108 LIBC_INLINE T
*operator->() { return &storage
.value(); }
109 LIBC_INLINE
constexpr const T
&operator*() const & { return value(); }
110 LIBC_INLINE T
&operator*() & { return value(); }
112 template <typename U
> LIBC_INLINE
constexpr T
value_or(U
&&value
) const & {
113 return has_value() ? value() : forward
<U
>(value
);
116 LIBC_INLINE T
&&value() && { return move(storage
.value()); }
117 LIBC_INLINE T
&&operator*() && { return move(storage
.value()); }
121 } // namespace __llvm_libc
123 #endif // LLVM_LIBC_SRC_SUPPORT_CPP_OPTIONAL_H