1 | /* |
2 | * Copyright (C) 2016-2017 Apple Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
19 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
20 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
21 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
22 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
23 | * THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | // Implementation of Library Fundamentals v3's std::expected, as described here: http://wg21.link/p0323r4 |
27 | |
28 | #pragma once |
29 | |
30 | /* |
31 | expected synopsis |
32 | |
33 | namespace std { |
34 | namespace experimental { |
35 | inline namespace fundamentals_v3 { |
36 | // ?.?.4, Expected for object types |
37 | template <class T, class E> |
38 | class expected; |
39 | |
40 | // ?.?.5, Expected specialization for void |
41 | template <class E> |
42 | class expected<void,E>; |
43 | |
44 | // ?.?.6, unexpect tag |
45 | struct unexpect_t { |
46 | unexpect_t() = default; |
47 | }; |
48 | inline constexpr unexpect_t unexpect{}; |
49 | |
50 | // ?.?.7, class bad_expected_access |
51 | template <class E> |
52 | class bad_expected_access; |
53 | |
54 | // ?.?.8, Specialization for void. |
55 | template <> |
56 | class bad_expected_access<void>; |
57 | |
58 | // ?.?.9, Expected relational operators |
59 | template <class T, class E> |
60 | constexpr bool operator==(const expected<T, E>&, const expected<T, E>&); |
61 | template <class T, class E> |
62 | constexpr bool operator!=(const expected<T, E>&, const expected<T, E>&); |
63 | |
64 | // ?.?.10, Comparison with T |
65 | template <class T, class E> |
66 | constexpr bool operator==(const expected<T, E>&, const T&); |
67 | template <class T, class E> |
68 | constexpr bool operator==(const T&, const expected<T, E>&); |
69 | template <class T, class E> |
70 | constexpr bool operator!=(const expected<T, E>&, const T&); |
71 | template <class T, class E> |
72 | constexpr bool operator!=(const T&, const expected<T, E>&); |
73 | |
74 | // ?.?.10, Comparison with unexpected<E> |
75 | template <class T, class E> |
76 | constexpr bool operator==(const expected<T, E>&, const unexpected<E>&); |
77 | template <class T, class E> |
78 | constexpr bool operator==(const unexpected<E>&, const expected<T, E>&); |
79 | template <class T, class E> |
80 | constexpr bool operator!=(const expected<T, E>&, const unexpected<E>&); |
81 | template <class T, class E> |
82 | constexpr bool operator!=(const unexpected<E>&, const expected<T, E>&); |
83 | |
84 | // ?.?.11, Specialized algorithms |
85 | void swap(expected<T, E>&, expected<T, E>&) noexcept(see below); |
86 | |
87 | template <class T, class E> |
88 | class expected |
89 | { |
90 | public: |
91 | typedef T value_type; |
92 | typedef E error_type; |
93 | typedef unexpected<E> unexpected_type; |
94 | |
95 | template <class U> |
96 | struct rebind { |
97 | using type = expected<U, error_type>; |
98 | }; |
99 | |
100 | // ?.?.4.1, constructors |
101 | constexpr expected(); |
102 | constexpr expected(const expected&); |
103 | constexpr expected(expected&&) noexcept(see below); |
104 | template <class U, class G> |
105 | EXPLICIT constexpr expected(const expected<U, G>&); |
106 | template <class U, class G> |
107 | EXPLICIT constexpr expected(expected<U, G>&&); |
108 | |
109 | template <class U = T> |
110 | EXPLICIT constexpr expected(U&& v); |
111 | |
112 | template <class... Args> |
113 | constexpr explicit expected(in_place_t, Args&&...); |
114 | template <class U, class... Args> |
115 | constexpr explicit expected(in_place_t, initializer_list<U>, Args&&...); |
116 | template <class G = E> |
117 | constexpr expected(unexpected<G> const&); |
118 | template <class G = E> |
119 | constexpr expected(unexpected<G> &&); |
120 | template <class... Args> |
121 | constexpr explicit expected(unexpect_t, Args&&...); |
122 | template <class U, class... Args> |
123 | constexpr explicit expected(unexpect_t, initializer_list<U>, Args&&...); |
124 | |
125 | // ?.?.4.2, destructor |
126 | ~expected(); |
127 | |
128 | // ?.?.4.3, assignment |
129 | expected& operator=(const expected&); |
130 | expected& operator=(expected&&) noexcept(see below); |
131 | template <class U = T> expected& operator=(U&&); |
132 | template <class G = E> |
133 | expected& operator=(const unexpected<G>&); |
134 | template <class G = E> |
135 | expected& operator=(unexpected<G>&&) noexcept(see below); |
136 | |
137 | template <class... Args> |
138 | void emplace(Args&&...); |
139 | template <class U, class... Args> |
140 | void emplace(initializer_list<U>, Args&&...); |
141 | |
142 | // ?.?.4.4, swap |
143 | void swap(expected&) noexcept(see below); |
144 | |
145 | // ?.?.4.5, observers |
146 | constexpr const T* operator ->() const; |
147 | constexpr T* operator ->(); |
148 | constexpr const T& operator *() const&; |
149 | constexpr T& operator *() &; |
150 | constexpr const T&& operator *() const &&; |
151 | constexpr T&& operator *() &&; |
152 | constexpr explicit operator bool() const noexcept; |
153 | constexpr bool has_value() const noexcept; |
154 | constexpr const T& value() const&; |
155 | constexpr T& value() &; |
156 | constexpr const T&& value() const &&; |
157 | constexpr T&& value() &&; |
158 | constexpr const E& error() const&; |
159 | constexpr E& error() &; |
160 | constexpr const E&& error() const &&; |
161 | constexpr E&& error() &&; |
162 | template <class U> |
163 | constexpr T value_or(U&&) const&; |
164 | template <class U> |
165 | T value_or(U&&) &&; |
166 | |
167 | private: |
168 | bool has_val; // exposition only |
169 | union |
170 | { |
171 | value_type val; // exposition only |
172 | unexpected_type unexpect; // exposition only |
173 | }; |
174 | }; |
175 | |
176 | }}} |
177 | |
178 | */ |
179 | |
180 | #include <cstdlib> |
181 | #include <initializer_list> |
182 | #include <type_traits> |
183 | #include <utility> |
184 | #include <wtf/Assertions.h> |
185 | #include <wtf/Compiler.h> |
186 | #include <wtf/StdLibExtras.h> |
187 | #include <wtf/Unexpected.h> |
188 | |
189 | namespace std { |
190 | namespace experimental { |
191 | inline namespace fundamentals_v3 { |
192 | |
193 | struct unexpected_t { |
194 | unexpected_t() = default; |
195 | }; |
196 | #if __cplusplus < 201703L |
197 | #define __EXPECTED_INLINE_VARIABLE static const |
198 | #else |
199 | #define __EXPECTED_INLINE_VARIABLE inline |
200 | #endif |
201 | |
202 | __EXPECTED_INLINE_VARIABLE constexpr unexpected_t unexpect { }; |
203 | |
204 | template<class E> class bad_expected_access; |
205 | |
206 | template<> |
207 | class bad_expected_access<void> : public std::exception { |
208 | public: |
209 | explicit bad_expected_access() { } |
210 | }; |
211 | |
212 | template<class E> |
213 | class bad_expected_access : public bad_expected_access<void> { |
214 | public: |
215 | explicit bad_expected_access(E val) : val(val) { } |
216 | virtual const char* what() const noexcept override { return std::exception::what(); } |
217 | E& error() & { return val; } |
218 | const E& error() const& { return val; } |
219 | E&& error() && { return std::move(val); } |
220 | const E&& error() const&& { return std::move(val); } |
221 | |
222 | private: |
223 | E val; |
224 | }; |
225 | |
226 | namespace __expected_detail { |
227 | |
228 | #if COMPILER_SUPPORTS(EXCEPTIONS) |
229 | #define __EXPECTED_THROW(__exception) (throw __exception) |
230 | #else |
231 | inline NO_RETURN_DUE_TO_CRASH void __expected_terminate() { RELEASE_ASSERT_NOT_REACHED(); } |
232 | #define __EXPECTED_THROW(...) __expected_detail::__expected_terminate() |
233 | #endif |
234 | |
235 | __EXPECTED_INLINE_VARIABLE constexpr enum class value_tag_t { } value_tag { }; |
236 | __EXPECTED_INLINE_VARIABLE constexpr enum class error_tag_t { } error_tag { }; |
237 | |
238 | template<class T, std::enable_if_t<std::is_trivially_destructible<T>::value>* = nullptr> void destroy(T&) { } |
239 | template<class T, std::enable_if_t<!std::is_trivially_destructible<T>::value && (std::is_class<T>::value || std::is_union<T>::value)>* = nullptr> void destroy(T& t) { t.~T(); } |
240 | |
241 | template<class T, class E> |
242 | union constexpr_storage { |
243 | typedef T value_type; |
244 | typedef E error_type; |
245 | typedef unexpected<E> unexpected_type; |
246 | char dummy; |
247 | value_type val; |
248 | error_type err; |
249 | constexpr constexpr_storage() : dummy() { } |
250 | constexpr constexpr_storage(value_tag_t) : val() { } |
251 | constexpr constexpr_storage(error_tag_t) : err() { } |
252 | template<typename U = T> |
253 | constexpr constexpr_storage(value_tag_t, U&& v) : val(std::forward<U>(v)) { } |
254 | template<typename U = E> |
255 | constexpr constexpr_storage(error_tag_t, U&& e) : err(std::forward<U>(e)) { } |
256 | ~constexpr_storage() = default; |
257 | }; |
258 | |
259 | template<class T, class E> |
260 | union storage { |
261 | typedef T value_type; |
262 | typedef E error_type; |
263 | typedef unexpected<E> unexpected_type; |
264 | char dummy; |
265 | value_type val; |
266 | error_type err; |
267 | constexpr storage() : dummy() { } |
268 | constexpr storage(value_tag_t) : val() { } |
269 | constexpr storage(error_tag_t) : err() { } |
270 | constexpr storage(value_tag_t, const value_type& val) : val(val) { } |
271 | constexpr storage(value_tag_t, value_type&& val) : val(std::forward<value_type>(val)) { } |
272 | constexpr storage(error_tag_t, const error_type& err) : err(err) { } |
273 | constexpr storage(error_tag_t, error_type&& err) : err(std::forward<error_type>(err)) { } |
274 | ~storage() { } |
275 | }; |
276 | |
277 | template<class E> |
278 | union constexpr_storage<void, E> { |
279 | typedef void value_type; |
280 | typedef E error_type; |
281 | typedef unexpected<E> unexpected_type; |
282 | char dummy; |
283 | error_type err; |
284 | constexpr constexpr_storage() : dummy() { } |
285 | constexpr constexpr_storage(value_tag_t) : dummy() { } |
286 | constexpr constexpr_storage(error_tag_t) : err() { } |
287 | constexpr constexpr_storage(error_tag_t, const error_type& e) : err(e) { } |
288 | ~constexpr_storage() = default; |
289 | }; |
290 | |
291 | template<class E> |
292 | union storage<void, E> { |
293 | typedef void value_type; |
294 | typedef E error_type; |
295 | typedef unexpected<E> unexpected_type; |
296 | char dummy; |
297 | error_type err; |
298 | constexpr storage() : dummy() { } |
299 | constexpr storage(value_tag_t) : dummy() { } |
300 | constexpr storage(error_tag_t) : err() { } |
301 | constexpr storage(error_tag_t, const error_type& err) : err(err) { } |
302 | constexpr storage(error_tag_t, error_type&& err) : err(std::forward<error_type>(err)) { } |
303 | ~storage() { } |
304 | }; |
305 | |
306 | template<class T, class E> |
307 | struct constexpr_base { |
308 | typedef T value_type; |
309 | typedef E error_type; |
310 | typedef unexpected<E> unexpected_type; |
311 | constexpr_storage<value_type, error_type> s; |
312 | bool has; |
313 | constexpr constexpr_base() : s(), has(true) { } |
314 | constexpr constexpr_base(value_tag_t tag) : s(tag), has(true) { } |
315 | constexpr constexpr_base(error_tag_t tag) : s(tag), has(false) { } |
316 | template<typename U = T> |
317 | constexpr constexpr_base(value_tag_t tag, U&& val) : s(tag, std::forward<U>(val)), has(true) { } |
318 | template<typename U = E> |
319 | constexpr constexpr_base(error_tag_t tag, U&& err) : s(tag, std::forward<U>(err)), has(false) { } |
320 | ~constexpr_base() = default; |
321 | }; |
322 | |
323 | template<class T, class E> |
324 | struct base { |
325 | typedef T value_type; |
326 | typedef E error_type; |
327 | typedef unexpected<E> unexpected_type; |
328 | storage<value_type, error_type> s; |
329 | bool has; |
330 | constexpr base() : s(), has(true) { } |
331 | constexpr base(value_tag_t tag) : s(tag), has(true) { } |
332 | constexpr base(error_tag_t tag) : s(tag), has(false) { } |
333 | constexpr base(value_tag_t tag, const value_type& val) : s(tag, val), has(true) { } |
334 | constexpr base(value_tag_t tag, value_type&& val) : s(tag, std::forward<value_type>(val)), has(true) { } |
335 | constexpr base(error_tag_t tag, const error_type& err) : s(tag, err), has(false) { } |
336 | constexpr base(error_tag_t tag, error_type&& err) : s(tag, std::forward<error_type>(err)), has(false) { } |
337 | base(const base& o) |
338 | : has(o.has) |
339 | { |
340 | if (has) |
341 | ::new (std::addressof(s.val)) value_type(o.s.val); |
342 | else |
343 | ::new (std::addressof(s.err)) error_type(o.s.err); |
344 | } |
345 | base(base&& o) |
346 | : has(o.has) |
347 | { |
348 | if (has) |
349 | ::new (std::addressof(s.val)) value_type(std::move(o.s.val)); |
350 | else |
351 | ::new (std::addressof(s.err)) error_type(std::move(o.s.err)); |
352 | } |
353 | ~base() |
354 | { |
355 | if (has) |
356 | destroy(s.val); |
357 | else |
358 | destroy(s.err); |
359 | } |
360 | }; |
361 | |
362 | template<class E> |
363 | struct constexpr_base<void, E> { |
364 | typedef void value_type; |
365 | typedef E error_type; |
366 | typedef unexpected<E> unexpected_type; |
367 | constexpr_storage<value_type, error_type> s; |
368 | bool has; |
369 | constexpr constexpr_base() : s(), has(true) { } |
370 | constexpr constexpr_base(value_tag_t tag) : s(tag), has(true) { } |
371 | constexpr constexpr_base(error_tag_t tag) : s(tag), has(false) { } |
372 | constexpr constexpr_base(error_tag_t tag, const error_type& err) : s(tag, err), has(false) { } |
373 | constexpr constexpr_base(error_tag_t tag, error_type&& err) : s(tag, std::forward<error_type>(err)), has(false) { } |
374 | ~constexpr_base() = default; |
375 | }; |
376 | |
377 | template<class E> |
378 | struct base<void, E> { |
379 | typedef void value_type; |
380 | typedef E error_type; |
381 | typedef unexpected<E> unexpected_type; |
382 | storage<value_type, error_type> s; |
383 | bool has; |
384 | constexpr base() : s(), has(true) { } |
385 | constexpr base(value_tag_t tag) : s(tag), has(true) { } |
386 | constexpr base(error_tag_t tag) : s(tag), has(false) { } |
387 | constexpr base(error_tag_t tag, const error_type& err) : s(tag, err), has(false) { } |
388 | constexpr base(error_tag_t tag, error_type&& err) : s(tag, std::forward<error_type>(err)), has(false) { } |
389 | base(const base& o) |
390 | : has(o.has) |
391 | { |
392 | if (!has) |
393 | ::new (std::addressof(s.err)) error_type(o.s.err); |
394 | } |
395 | base(base&& o) |
396 | : has(o.has) |
397 | { |
398 | if (!has) |
399 | ::new (std::addressof(s.err)) error_type(std::move(o.s.err)); |
400 | } |
401 | ~base() |
402 | { |
403 | if (!has) |
404 | destroy(s.err); |
405 | } |
406 | }; |
407 | |
408 | template<class T, class E> |
409 | using base_select = typename std::conditional< |
410 | ((std::is_void<T>::value || std::is_trivially_destructible<T>::value) |
411 | && std::is_trivially_destructible<E>::value), |
412 | constexpr_base<typename std::remove_const<T>::type, typename std::remove_const<E>::type>, |
413 | base<typename std::remove_const<T>::type, typename std::remove_const<E>::type> |
414 | >::type; |
415 | |
416 | } // namespace __expected_detail |
417 | |
418 | template<class T, class E> |
419 | class expected : private __expected_detail::base_select<T, E> { |
420 | WTF_MAKE_FAST_ALLOCATED; |
421 | typedef __expected_detail::base_select<T, E> base; |
422 | |
423 | public: |
424 | typedef typename base::value_type value_type; |
425 | typedef typename base::error_type error_type; |
426 | typedef typename base::unexpected_type unexpected_type; |
427 | |
428 | private: |
429 | typedef expected<value_type, error_type> type; |
430 | |
431 | public: |
432 | template<class U> struct rebind { |
433 | using type = expected<U, error_type>; |
434 | }; |
435 | |
436 | constexpr expected() : base(__expected_detail::value_tag) { } |
437 | expected(const expected&) = default; |
438 | expected(expected&&) = default; |
439 | |
440 | constexpr expected(const value_type& e) : base(__expected_detail::value_tag, e) { } |
441 | constexpr expected(value_type&& e) : base(__expected_detail::value_tag, std::forward<value_type>(e)) { } |
442 | template<class... Args> constexpr explicit expected(std::in_place_t, Args&&... args) : base(__expected_detail::value_tag, value_type(std::forward<Args>(args)...)) { } |
443 | // template<class U, class... Args> constexpr explicit expected(in_place_t, std::initializer_list<U>, Args&&...); |
444 | constexpr expected(const unexpected_type& u) : base(__expected_detail::error_tag, u.value()) { } |
445 | constexpr expected(unexpected_type&& u) : base(__expected_detail::error_tag, std::forward<unexpected_type>(u).value()) { } |
446 | template<class Err> constexpr expected(const unexpected<Err>& u) : base(__expected_detail::error_tag, u.value()) { } |
447 | template<class Err> constexpr expected(unexpected<Err>&& u) : base(__expected_detail::error_tag, std::forward<Err>(u.value())) { } |
448 | template<class... Args> constexpr explicit expected(unexpected_t, Args&&... args) : base(__expected_detail::value_tag, unexpected_type(std::forward<Args>(args)...)) { } |
449 | // template<class U, class... Args> constexpr explicit expected(unexpected_t, std::initializer_list<U>, Args&&...); |
450 | |
451 | ~expected() = default; |
452 | |
453 | expected& operator=(const expected& e) { type(e).swap(*this); return *this; } |
454 | expected& operator=(expected&& e) { type(std::move(e)).swap(*this); return *this; } |
455 | template<class U> expected& operator=(U&& u) { type(std::move(u)).swap(*this); return *this; } |
456 | expected& operator=(const unexpected_type& u) { type(u).swap(*this); return *this; } |
457 | expected& operator=(unexpected_type&& u) { type(std::move(u)).swap(*this); return *this; } |
458 | // template<class... Args> void emplace(Args&&...); |
459 | // template<class U, class... Args> void emplace(std::initializer_list<U>, Args&&...); |
460 | |
461 | void swap(expected& o) |
462 | { |
463 | using std::swap; |
464 | if (base::has && o.has) |
465 | swap(base::s.val, o.s.val); |
466 | else if (base::has && !o.has) { |
467 | error_type e(std::move(o.s.err)); |
468 | __expected_detail::destroy(o.s.err); |
469 | ::new (std::addressof(o.s.val)) value_type(std::move(base::s.val)); |
470 | __expected_detail::destroy(base::s.val); |
471 | ::new (std::addressof(base::s.err)) error_type(std::move(e)); |
472 | swap(base::has, o.has); |
473 | } else if (!base::has && o.has) { |
474 | value_type v(std::move(o.s.val)); |
475 | __expected_detail::destroy(o.s.val); |
476 | ::new (std::addressof(o.s.err)) error_type(std::move(base::s.err)); |
477 | __expected_detail::destroy(base::s.err); |
478 | ::new (std::addressof(base::s.val)) value_type(std::move(v)); |
479 | swap(base::has, o.has); |
480 | } else |
481 | swap(base::s.err, o.s.err); |
482 | } |
483 | |
484 | constexpr const value_type* operator->() const { return &base::s.val; } |
485 | value_type* operator->() { return &base::s.val; } |
486 | constexpr const value_type& operator*() const & { return base::s.val; } |
487 | value_type& operator*() & { return base::s.val; } |
488 | constexpr const value_type&& operator*() const && { return std::move(base::s.val); } |
489 | constexpr value_type&& operator*() && { return std::move(base::s.val); } |
490 | constexpr explicit operator bool() const { return base::has; } |
491 | constexpr bool has_value() const { return base::has; } |
492 | constexpr const value_type& value() const & { return base::has ? base::s.val : (__EXPECTED_THROW(bad_expected_access<error_type>(base::s.err)), base::s.val); } |
493 | constexpr value_type& value() & { return base::has ? base::s.val : (__EXPECTED_THROW(bad_expected_access<error_type>(base::s.err)), base::s.val); } |
494 | constexpr const value_type&& value() const && { return std::move(base::has ? base::s.val : (__EXPECTED_THROW(bad_expected_access<error_type>(base::s.err)), base::s.val)); } |
495 | constexpr value_type&& value() && { return std::move(base::has ? base::s.val : (__EXPECTED_THROW(bad_expected_access<error_type>(base::s.err)), base::s.val)); } |
496 | constexpr const error_type& error() const & { return !base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err); } |
497 | error_type& error() & { return !base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err); } |
498 | constexpr error_type&& error() && { return std::move(!base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err)); } |
499 | constexpr const error_type&& error() const && { return std::move(!base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err)); } |
500 | template<class U> constexpr value_type value_or(U&& u) const & { return base::has ? **this : static_cast<value_type>(std::forward<U>(u)); } |
501 | template<class U> value_type value_or(U&& u) && { return base::has ? std::move(**this) : static_cast<value_type>(std::forward<U>(u)); } |
502 | }; |
503 | |
504 | template<class E> |
505 | class expected<void, E> : private __expected_detail::base_select<void, E> { |
506 | typedef __expected_detail::base_select<void, E> base; |
507 | |
508 | public: |
509 | typedef typename base::value_type value_type; |
510 | typedef typename base::error_type error_type; |
511 | typedef typename base::unexpected_type unexpected_type; |
512 | |
513 | private: |
514 | typedef expected<value_type, error_type> type; |
515 | |
516 | public: |
517 | template<class U> struct rebind { |
518 | using type = expected<U, error_type>; |
519 | }; |
520 | |
521 | constexpr expected() : base(__expected_detail::value_tag) { } |
522 | expected(const expected&) = default; |
523 | expected(expected&&) = default; |
524 | // constexpr explicit expected(in_place_t); |
525 | constexpr expected(unexpected_type const& u) : base(__expected_detail::error_tag, u.value()) { } |
526 | constexpr expected(unexpected_type&& u) : base(__expected_detail::error_tag, std::forward<unexpected_type>(u).value()) { } |
527 | template<class Err> constexpr expected(unexpected<Err> const& u) : base(__expected_detail::error_tag, u.value()) { } |
528 | |
529 | ~expected() = default; |
530 | |
531 | expected& operator=(const expected& e) { type(e).swap(*this); return *this; } |
532 | expected& operator=(expected&& e) { type(std::move(e)).swap(*this); return *this; } |
533 | expected& operator=(const unexpected_type& u) { type(u).swap(*this); return *this; } // Not in the current paper. |
534 | expected& operator=(unexpected_type&& u) { type(std::move(u)).swap(*this); return *this; } // Not in the current paper. |
535 | // void emplace(); |
536 | |
537 | void swap(expected& o) |
538 | { |
539 | using std::swap; |
540 | if (base::has && o.has) { |
541 | // Do nothing. |
542 | } else if (base::has && !o.has) { |
543 | error_type e(std::move(o.s.err)); |
544 | ::new (std::addressof(base::s.err)) error_type(e); |
545 | swap(base::has, o.has); |
546 | } else if (!base::has && o.has) { |
547 | ::new (std::addressof(o.s.err)) error_type(std::move(base::s.err)); |
548 | swap(base::has, o.has); |
549 | } else |
550 | swap(base::s.err, o.s.err); |
551 | } |
552 | |
553 | constexpr explicit operator bool() const { return base::has; } |
554 | constexpr bool has_value() const { return base::has; } |
555 | void value() const { !base::has ? __EXPECTED_THROW(bad_expected_access<void>()) : void(); } |
556 | constexpr const E& error() const & { return !base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err); } |
557 | E& error() & { return !base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err); } |
558 | constexpr E&& error() && { return std::move(!base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err)); } |
559 | }; |
560 | |
561 | template<class T, class E> constexpr bool operator==(const expected<T, E>& x, const expected<T, E>& y) { return bool(x) == bool(y) && (x ? x.value() == y.value() : x.error() == y.error()); } |
562 | template<class T, class E> constexpr bool operator!=(const expected<T, E>& x, const expected<T, E>& y) { return !(x == y); } |
563 | |
564 | template<class E> constexpr bool operator==(const expected<void, E>& x, const expected<void, E>& y) { return bool(x) == bool(y) && (x ? true : x.error() == y.error()); } |
565 | |
566 | template<class T, class E> constexpr bool operator==(const expected<T, E>& x, const T& y) { return x ? *x == y : false; } |
567 | template<class T, class E> constexpr bool operator==(const T& x, const expected<T, E>& y) { return y ? x == *y : false; } |
568 | template<class T, class E> constexpr bool operator!=(const expected<T, E>& x, const T& y) { return x ? *x != y : true; } |
569 | template<class T, class E> constexpr bool operator!=(const T& x, const expected<T, E>& y) { return y ? x != *y : true; } |
570 | |
571 | template<class T, class E> constexpr bool operator==(const expected<T, E>& x, const unexpected<E>& y) { return x ? false : x.error() == y.value(); } |
572 | template<class T, class E> constexpr bool operator==(const unexpected<E>& x, const expected<T, E>& y) { return y ? false : x.value() == y.error(); } |
573 | template<class T, class E> constexpr bool operator!=(const expected<T, E>& x, const unexpected<E>& y) { return x ? true : x.error() != y.value(); } |
574 | template<class T, class E> constexpr bool operator!=(const unexpected<E>& x, const expected<T, E>& y) { return y ? true : x.value() != y.error(); } |
575 | |
576 | template<typename T, typename E> void swap(expected<T, E>& x, expected<T, E>& y) { x.swap(y); } |
577 | |
578 | }}} // namespace std::experimental::fundamentals_v3 |
579 | |
580 | __EXPECTED_INLINE_VARIABLE constexpr auto& unexpect = std::experimental::unexpect; |
581 | template<class T, class E> using Expected = std::experimental::expected<T, E>; |
582 | |