@@ -195,16 +195,28 @@ template <class T> inline void *_Nonnull getOpaquePointer(T &value) {
195
195
196
196
} // namespace _impl
197
197
198
+ constexpr static std::size_t max (std::size_t a, std::size_t b) {
199
+ return a > b ? a : b;
200
+ }
201
+
198
202
// / The Expected class has either an error or an value.
199
203
template <class T >
200
204
class Expected {
201
205
public:
202
206
203
207
// / Default
204
- constexpr Expected () { has_val = false ; }
205
- constexpr Expected (const swift::Error& error_val) : err(error_val) { has_val = false ; }
206
- constexpr Expected (T buf) {
207
- new (&buffer) T (buf);
208
+ constexpr Expected () noexcept {
209
+ new (&buffer) Error ();
210
+ has_val = false ;
211
+ }
212
+
213
+ constexpr Expected (const swift::Error& error_val) noexcept {
214
+ new (&buffer) Error (error_val);
215
+ has_val = false ;
216
+ }
217
+
218
+ constexpr Expected (const T &val) noexcept {
219
+ new (&buffer) T (val);
208
220
has_val = true ;
209
221
}
210
222
@@ -213,38 +225,55 @@ class Expected {
213
225
if (other.has_value ())
214
226
new (&buffer) T (other.value ());
215
227
else
216
- new (&err ) Error (other.error ());
228
+ new (&buffer ) Error (other.error ());
217
229
218
230
has_val = other.has_value ();
219
231
}
232
+
220
233
// / Move
221
234
// FIXME: Implement move semantics when move Swift values is possible
222
235
constexpr Expected (Expected&&) noexcept { abort (); }
223
236
224
- ~Expected () noexcept { }
237
+ ~Expected () noexcept {
238
+ if (has_value ())
239
+ reinterpret_cast <const T *>(buffer)->~T ();
240
+ else
241
+ reinterpret_cast <swift::Error *>(buffer)->~Error ();
242
+ }
225
243
226
244
// / assignment
227
- constexpr auto operator =(Expected&& other) noexcept { auto temp = buffer; buffer = other. buffer ; other. buffer = temp; }
245
+ constexpr auto operator =(Expected&& other) noexcept = delete ;
228
246
constexpr auto operator =(Expected&) noexcept = delete ;
229
247
230
248
// / For accessing T's members
231
- // precondition: has_value() == true
232
- constexpr T const *_Nonnull operator ->() const noexcept { return reinterpret_cast <const T *>(buffer); }
249
+ constexpr T const *_Nonnull operator ->() const noexcept {
250
+ if (!has_value ())
251
+ abort ();
252
+ return reinterpret_cast <const T *>(buffer);
253
+ }
233
254
234
- // precondition: has_value() == true
235
- constexpr T *_Nonnull operator ->() noexcept { return reinterpret_cast <T *>(buffer); }
255
+ constexpr T *_Nonnull operator ->() noexcept {
256
+ if (!has_value ())
257
+ abort ();
258
+ return reinterpret_cast <T *>(buffer);
259
+ }
236
260
237
261
// / Getting reference to T
238
- // precondition: has_value() == true
239
- constexpr T const &operator *() const & noexcept { return reinterpret_cast <const T &>(buffer); }
262
+ constexpr T const &operator *() const & noexcept {
263
+ if (!has_value ())
264
+ abort ();
265
+ return reinterpret_cast <const T &>(buffer);
266
+ }
240
267
241
- // precondition: has_value() == true
242
- constexpr T &operator *() & noexcept { return reinterpret_cast <T &>(buffer); }
268
+ constexpr T &operator *() & noexcept {
269
+ if (!has_value ())
270
+ abort ();
271
+ return reinterpret_cast <T &>(buffer);
272
+ }
243
273
244
274
constexpr explicit operator bool () const noexcept { return has_value (); }
245
275
246
276
// Get value, if not exists abort
247
- // FIXME: throw exception instead of abort?
248
277
constexpr T const & value () const & {
249
278
if (!has_value ())
250
279
abort ();
@@ -261,19 +290,19 @@ class Expected {
261
290
constexpr swift::Error const & error () const & {
262
291
if (has_value ())
263
292
abort ();
264
- return err ;
293
+ return reinterpret_cast < const swift::Error&>(buffer) ;
265
294
}
295
+
266
296
constexpr swift::Error& error () & {
267
297
if (has_value ())
268
298
abort ();
269
- return err ;
299
+ return reinterpret_cast <swift::Error&>(buffer) ;
270
300
}
271
301
272
302
constexpr bool has_value () const noexcept { return has_val; }
273
303
274
304
private:
275
- alignas (alignof (T)) char buffer[sizeof (T)];
276
- swift::Error err;
305
+ alignas (max(alignof (T), alignof (swift::Error))) char buffer[max(sizeof (T), sizeof (swift::Error))];
277
306
bool has_val;
278
307
};
279
308
0 commit comments