|
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