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
33namespace std {
34namespace experimental {
35inline 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
189namespace std {
190namespace experimental {
191inline namespace fundamentals_v3 {
192
193struct 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
204template<class E> class bad_expected_access;
205
206template<>
207class bad_expected_access<void> : public std::exception {
208public:
209 explicit bad_expected_access() { }
210};
211
212template<class E>
213class bad_expected_access : public bad_expected_access<void> {
214public:
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
222private:
223 E val;
224};
225
226namespace __expected_detail {
227
228#if COMPILER_SUPPORTS(EXCEPTIONS)
229#define __EXPECTED_THROW(__exception) (throw __exception)
230#else
231inline 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
238template<class T, std::enable_if_t<std::is_trivially_destructible<T>::value>* = nullptr> void destroy(T&) { }
239template<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
241template<class T, class E>
242union 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
259template<class T, class E>
260union 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
277template<class E>
278union 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
291template<class E>
292union 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
306template<class T, class E>
307struct 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
323template<class T, class E>
324struct 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
362template<class E>
363struct 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
377template<class E>
378struct 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
408template<class T, class E>
409using 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
418template<class T, class E>
419class expected : private __expected_detail::base_select<T, E> {
420 typedef __expected_detail::base_select<T, E> base;
421
422public:
423 typedef typename base::value_type value_type;
424 typedef typename base::error_type error_type;
425 typedef typename base::unexpected_type unexpected_type;
426
427private:
428 typedef expected<value_type, error_type> type;
429
430public:
431 template<class U> struct rebind {
432 using type = expected<U, error_type>;
433 };
434
435 constexpr expected() : base(__expected_detail::value_tag) { }
436 expected(const expected&) = default;
437 expected(expected&&) = default;
438
439 constexpr expected(const value_type& e) : base(__expected_detail::value_tag, e) { }
440 constexpr expected(value_type&& e) : base(__expected_detail::value_tag, std::forward<value_type>(e)) { }
441 template<class... Args> constexpr explicit expected(std::in_place_t, Args&&... args) : base(__expected_detail::value_tag, value_type(std::forward<Args>(args)...)) { }
442 // template<class U, class... Args> constexpr explicit expected(in_place_t, std::initializer_list<U>, Args&&...);
443 constexpr expected(const unexpected_type& u) : base(__expected_detail::error_tag, u.value()) { }
444 constexpr expected(unexpected_type&& u) : base(__expected_detail::error_tag, std::forward<unexpected_type>(u).value()) { }
445 template<class Err> constexpr expected(const unexpected<Err>& u) : base(__expected_detail::error_tag, u.value()) { }
446 template<class Err> constexpr expected(unexpected<Err>&& u) : base(__expected_detail::error_tag, std::forward<Err>(u.value())) { }
447 template<class... Args> constexpr explicit expected(unexpected_t, Args&&... args) : base(__expected_detail::value_tag, unexpected_type(std::forward<Args>(args)...)) { }
448 // template<class U, class... Args> constexpr explicit expected(unexpected_t, std::initializer_list<U>, Args&&...);
449
450 ~expected() = default;
451
452 expected& operator=(const expected& e) { type(e).swap(*this); return *this; }
453 expected& operator=(expected&& e) { type(std::move(e)).swap(*this); return *this; }
454 template<class U> expected& operator=(U&& u) { type(std::move(u)).swap(*this); return *this; }
455 expected& operator=(const unexpected_type& u) { type(u).swap(*this); return *this; }
456 expected& operator=(unexpected_type&& u) { type(std::move(u)).swap(*this); return *this; }
457 // template<class... Args> void emplace(Args&&...);
458 // template<class U, class... Args> void emplace(std::initializer_list<U>, Args&&...);
459
460 void swap(expected& o)
461 {
462 using std::swap;
463 if (base::has && o.has)
464 swap(base::s.val, o.s.val);
465 else if (base::has && !o.has) {
466 error_type e(std::move(o.s.err));
467 __expected_detail::destroy(o.s.err);
468 ::new (std::addressof(o.s.val)) value_type(std::move(base::s.val));
469 __expected_detail::destroy(base::s.val);
470 ::new (std::addressof(base::s.err)) error_type(std::move(e));
471 swap(base::has, o.has);
472 } else if (!base::has && o.has) {
473 value_type v(std::move(o.s.val));
474 __expected_detail::destroy(o.s.val);
475 ::new (std::addressof(o.s.err)) error_type(std::move(base::s.err));
476 __expected_detail::destroy(base::s.err);
477 ::new (std::addressof(base::s.val)) value_type(std::move(v));
478 swap(base::has, o.has);
479 } else
480 swap(base::s.err, o.s.err);
481 }
482
483 constexpr const value_type* operator->() const { return &base::s.val; }
484 value_type* operator->() { return &base::s.val; }
485 constexpr const value_type& operator*() const & { return base::s.val; }
486 value_type& operator*() & { return base::s.val; }
487 constexpr const value_type&& operator*() const && { return std::move(base::s.val); }
488 constexpr value_type&& operator*() && { return std::move(base::s.val); }
489 constexpr explicit operator bool() const { return base::has; }
490 constexpr bool has_value() const { return base::has; }
491 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); }
492 constexpr value_type& value() & { return base::has ? base::s.val : (__EXPECTED_THROW(bad_expected_access<error_type>(base::s.err)), base::s.val); }
493 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)); }
494 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)); }
495 constexpr const error_type& error() const & { return !base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err); }
496 error_type& error() & { return !base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err); }
497 constexpr error_type&& error() && { return std::move(!base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err)); }
498 constexpr const error_type&& error() const && { return std::move(!base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err)); }
499 template<class U> constexpr value_type value_or(U&& u) const & { return base::has ? **this : static_cast<value_type>(std::forward<U>(u)); }
500 template<class U> value_type value_or(U&& u) && { return base::has ? std::move(**this) : static_cast<value_type>(std::forward<U>(u)); }
501};
502
503template<class E>
504class expected<void, E> : private __expected_detail::base_select<void, E> {
505 typedef __expected_detail::base_select<void, E> base;
506
507public:
508 typedef typename base::value_type value_type;
509 typedef typename base::error_type error_type;
510 typedef typename base::unexpected_type unexpected_type;
511
512private:
513 typedef expected<value_type, error_type> type;
514
515public:
516 template<class U> struct rebind {
517 using type = expected<U, error_type>;
518 };
519
520 constexpr expected() : base(__expected_detail::value_tag) { }
521 expected(const expected&) = default;
522 expected(expected&&) = default;
523 // constexpr explicit expected(in_place_t);
524 constexpr expected(unexpected_type const& u) : base(__expected_detail::error_tag, u.value()) { }
525 constexpr expected(unexpected_type&& u) : base(__expected_detail::error_tag, std::forward<unexpected_type>(u).value()) { }
526 template<class Err> constexpr expected(unexpected<Err> const& u) : base(__expected_detail::error_tag, u.value()) { }
527
528 ~expected() = default;
529
530 expected& operator=(const expected& e) { type(e).swap(*this); return *this; }
531 expected& operator=(expected&& e) { type(std::move(e)).swap(*this); return *this; }
532 expected& operator=(const unexpected_type& u) { type(u).swap(*this); return *this; } // Not in the current paper.
533 expected& operator=(unexpected_type&& u) { type(std::move(u)).swap(*this); return *this; } // Not in the current paper.
534 // void emplace();
535
536 void swap(expected& o)
537 {
538 using std::swap;
539 if (base::has && o.has) {
540 // Do nothing.
541 } else if (base::has && !o.has) {
542 error_type e(std::move(o.s.err));
543 ::new (std::addressof(base::s.err)) error_type(e);
544 swap(base::has, o.has);
545 } else if (!base::has && o.has) {
546 ::new (std::addressof(o.s.err)) error_type(std::move(base::s.err));
547 swap(base::has, o.has);
548 } else
549 swap(base::s.err, o.s.err);
550 }
551
552 constexpr explicit operator bool() const { return base::has; }
553 constexpr bool has_value() const { return base::has; }
554 void value() const { !base::has ? __EXPECTED_THROW(bad_expected_access<void>()) : void(); }
555 constexpr const E& error() const & { return !base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err); }
556 E& error() & { return !base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err); }
557 constexpr E&& error() && { return std::move(!base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err)); }
558};
559
560template<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()); }
561template<class T, class E> constexpr bool operator!=(const expected<T, E>& x, const expected<T, E>& y) { return !(x == y); }
562
563template<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()); }
564
565template<class T, class E> constexpr bool operator==(const expected<T, E>& x, const T& y) { return x ? *x == y : false; }
566template<class T, class E> constexpr bool operator==(const T& x, const expected<T, E>& y) { return y ? x == *y : false; }
567template<class T, class E> constexpr bool operator!=(const expected<T, E>& x, const T& y) { return x ? *x != y : true; }
568template<class T, class E> constexpr bool operator!=(const T& x, const expected<T, E>& y) { return y ? x != *y : true; }
569
570template<class T, class E> constexpr bool operator==(const expected<T, E>& x, const unexpected<E>& y) { return x ? false : x.error() == y.value(); }
571template<class T, class E> constexpr bool operator==(const unexpected<E>& x, const expected<T, E>& y) { return y ? false : x.value() == y.error(); }
572template<class T, class E> constexpr bool operator!=(const expected<T, E>& x, const unexpected<E>& y) { return x ? true : x.error() != y.value(); }
573template<class T, class E> constexpr bool operator!=(const unexpected<E>& x, const expected<T, E>& y) { return y ? true : x.value() != y.error(); }
574
575template<typename T, typename E> void swap(expected<T, E>& x, expected<T, E>& y) { x.swap(y); }
576
577}}} // namespace std::experimental::fundamentals_v3
578
579__EXPECTED_INLINE_VARIABLE constexpr auto& unexpect = std::experimental::unexpect;
580template<class T, class E> using Expected = std::experimental::expected<T, E>;
581