|
8 | 8 |
|
9 | 9 | #pragma once
|
10 | 10 |
|
11 |
| -#include <executorch/runtime/platform/assert.h> |
12 |
| -#include <new> |
13 |
| -#include <utility> // std::forward and other template magic checks |
| 11 | +#include <optional> |
14 | 12 |
|
15 | 13 | namespace executorch {
|
16 | 14 | namespace runtime {
|
17 | 15 | namespace etensor {
|
18 | 16 |
|
19 |
| -/// Used to indicate an optional type with uninitialized state. |
20 |
| -struct nullopt_t final { |
21 |
| - constexpr explicit nullopt_t(int32_t) {} |
22 |
| -}; |
23 |
| - |
24 |
| -/// A constant of type nullopt_t that is used to indicate an optional type with |
25 |
| -/// uninitialized state. |
26 |
| -constexpr nullopt_t nullopt{0}; |
27 |
| - |
28 |
| -/// Leaner optional class, subset of c10, std, and boost optional APIs. |
29 |
| -template <class T> |
30 |
| -class optional final { |
31 |
| - public: |
32 |
| - /// The type wrapped by the optional class. |
33 |
| - using value_type = T; |
34 |
| - |
35 |
| - /// Constructs an optional object that does not contain a value. |
36 |
| - /* implicit */ optional() noexcept : storage_(trivial_init), init_(false) {} |
37 |
| - |
38 |
| - /// Constructs an optional object that does not contain a value. |
39 |
| - /* implicit */ optional(nullopt_t) noexcept |
40 |
| - : storage_(trivial_init), init_(false) {} |
41 |
| - |
42 |
| - /// Constructs an optional object that matches the state of v. |
43 |
| - /* implicit */ optional(const optional<T>& v) |
44 |
| - : storage_(trivial_init), init_(v.init_) { |
45 |
| - if (init_) { |
46 |
| - new (&storage_.value_) T(v.storage_.value_); |
47 |
| - } |
48 |
| - } |
49 |
| - |
50 |
| - /// Constructs an optional object that contains the specified value. |
51 |
| - /* implicit */ optional(const T& v) : storage_(v), init_(true) {} |
52 |
| - |
53 |
| - /// Constructs an optional object from v. |
54 |
| - /* implicit */ optional(optional<T>&& v) noexcept( |
55 |
| - std::is_nothrow_move_constructible<T>::value) |
56 |
| - : storage_(trivial_init), init_(v.init_) { |
57 |
| - if (init_) { |
58 |
| - new (&storage_.value_) T(std::forward<T>(v.storage_.value_)); |
59 |
| - } |
60 |
| - } |
61 |
| - |
62 |
| - /// Constructs an optional object that contains the specified value. |
63 |
| - /* implicit */ optional(T&& v) : storage_(std::forward<T>(v)), init_(true) {} |
64 |
| - |
65 |
| - optional& operator=(const optional& rhs) { |
66 |
| - if (init_ && !rhs.init_) { |
67 |
| - clear(); |
68 |
| - } else if (!init_ && rhs.init_) { |
69 |
| - init_ = true; |
70 |
| - new (&storage_.value_) T(rhs.storage_.value_); |
71 |
| - } else if (init_ && rhs.init_) { |
72 |
| - storage_.value_ = rhs.storage_.value_; |
73 |
| - } |
74 |
| - return *this; |
75 |
| - } |
76 |
| - |
77 |
| - optional& operator=(optional&& rhs) noexcept( |
78 |
| - std::is_nothrow_move_assignable<T>::value && |
79 |
| - std::is_nothrow_move_constructible<T>::value) { |
80 |
| - if (init_ && !rhs.init_) { |
81 |
| - clear(); |
82 |
| - } else if (!init_ && rhs.init_) { |
83 |
| - init_ = true; |
84 |
| - new (&storage_.value_) T(std::forward<T>(rhs.storage_.value_)); |
85 |
| - } else if (init_ && rhs.init_) { |
86 |
| - storage_.value_ = std::forward<T>(rhs.storage_.value_); |
87 |
| - } |
88 |
| - return *this; |
89 |
| - } |
90 |
| - |
91 |
| - /// Destroys the stored value if there is one |
92 |
| - ~optional() { |
93 |
| - if (init_) { |
94 |
| - storage_.value_.~T(); |
95 |
| - } |
96 |
| - } |
97 |
| - |
98 |
| - optional& operator=(nullopt_t) noexcept { |
99 |
| - clear(); |
100 |
| - return *this; |
101 |
| - } |
102 |
| - |
103 |
| - /// Returns true if the object contains a value, false otherwise |
104 |
| - explicit operator bool() const noexcept { |
105 |
| - return init_; |
106 |
| - } |
107 |
| - |
108 |
| - /// Returns true if the object contains a value, false otherwise |
109 |
| - bool has_value() const noexcept { |
110 |
| - return init_; |
111 |
| - } |
112 |
| - |
113 |
| - /// Returns a constant reference to the contained value. Calls ET_CHECK if |
114 |
| - /// the object does not contain a value. |
115 |
| - T const& value() const& { |
116 |
| - ET_CHECK(init_); |
117 |
| - return contained_val(); |
118 |
| - } |
119 |
| - |
120 |
| - /// Returns a mutable reference to the contained value. Calls ET_CHECK if the |
121 |
| - /// object does not contain a value. |
122 |
| - T& value() & { |
123 |
| - ET_CHECK(init_); |
124 |
| - return contained_val(); |
125 |
| - } |
126 |
| - |
127 |
| - /// Returns an rvalue of the contained value. Calls ET_CHECK if the object |
128 |
| - /// does not contain a value. |
129 |
| - T&& value() && { |
130 |
| - ET_CHECK(init_); |
131 |
| - return std::forward<T>(contained_val()); |
132 |
| - } |
133 |
| - |
134 |
| - private: |
135 |
| - // Used to invoke the dummy ctor of storage_t in the initializer lists of |
136 |
| - // optional_base as default ctor is implicitly deleted because T is nontrivial |
137 |
| - struct trivial_init_t { |
138 |
| - } trivial_init{}; |
139 |
| - |
140 |
| - /** |
141 |
| - * A wrapper type that lets us avoid constructing a T when there is no value. |
142 |
| - * If there is a value present, the optional class must destroy it. |
143 |
| - */ |
144 |
| - union storage_t { |
145 |
| - /// A small, trivially-constructable alternative to T. |
146 |
| - unsigned char dummy_; |
147 |
| - /// The constructed value itself, if optional::has_value_ is true. |
148 |
| - T value_; |
149 |
| - |
150 |
| - /* implicit */ storage_t(trivial_init_t) { |
151 |
| - dummy_ = 0; |
152 |
| - } |
153 |
| - |
154 |
| - template <class... Args> |
155 |
| - storage_t(Args&&... args) : value_(std::forward<Args>(args)...) {} |
156 |
| - |
157 |
| - ~storage_t() {} |
158 |
| - }; |
159 |
| - |
160 |
| - const T& contained_val() const& { |
161 |
| - return storage_.value_; |
162 |
| - } |
163 |
| - T&& contained_val() && { |
164 |
| - return std::move(storage_.value_); |
165 |
| - } |
166 |
| - T& contained_val() & { |
167 |
| - return storage_.value_; |
168 |
| - } |
169 |
| - |
170 |
| - void clear() noexcept { |
171 |
| - if (init_) { |
172 |
| - storage_.value_.~T(); |
173 |
| - } |
174 |
| - init_ = false; |
175 |
| - } |
176 |
| - |
177 |
| - storage_t storage_; |
178 |
| - bool init_; |
179 |
| -}; |
| 17 | +// NOLINTNEXTLINE(misc-unused-using-decls) |
| 18 | +using std::nullopt; |
| 19 | +// NOLINTNEXTLINE(misc-unused-using-decls) |
| 20 | +using std::nullopt_t; |
| 21 | +// NOLINTNEXTLINE(misc-unused-using-decls) |
| 22 | +using std::optional; |
180 | 23 |
|
181 | 24 | } // namespace etensor
|
182 | 25 | } // namespace runtime
|
|
0 commit comments