Unreviewed, rolling out r231223 and r231288.
[WebKit-https.git] / Source / WTF / wtf / Expected.h
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/Optional.h>
187 #include <wtf/StdLibExtras.h>
188 #include <wtf/Unexpected.h>
189
190 namespace std {
191 namespace experimental {
192 inline namespace fundamentals_v3 {
193
194 struct unexpected_t {
195     unexpected_t() = default;
196 };
197 #if __cplusplus < 201703L
198 #define __EXPECTED_INLINE_VARIABLE static const
199 #else
200 #define __EXPECTED_INLINE_VARIABLE inline
201 #endif
202
203 __EXPECTED_INLINE_VARIABLE constexpr unexpected_t unexpect { };
204
205 template<class E> class bad_expected_access;
206
207 template<>
208 class bad_expected_access<void> : public std::exception {
209 public:
210     explicit bad_expected_access() { }
211 };
212
213 template<class E>
214 class bad_expected_access : public bad_expected_access<void> {
215 public:
216     explicit bad_expected_access(E val) : val(val) { }
217     virtual const char* what() const noexcept override { return std::exception::what(); }
218     E& error() & { return val; }
219     const E& error() const& { return val; }
220     E&& error() && { return std::move(val); }
221     const E&&  error() const&& { return std::move(val); }
222
223 private:
224     E val;
225 };
226
227 namespace __expected_detail {
228
229 #if COMPILER_SUPPORTS(EXCEPTIONS)
230 #define __EXPECTED_THROW(__exception) (throw __exception)
231 #else
232 inline NO_RETURN_DUE_TO_CRASH void __expected_terminate() { RELEASE_ASSERT_NOT_REACHED(); }
233 #define __EXPECTED_THROW(...) __expected_detail::__expected_terminate()
234 #endif
235
236 __EXPECTED_INLINE_VARIABLE constexpr enum class value_tag_t { } value_tag { };
237 __EXPECTED_INLINE_VARIABLE constexpr enum class error_tag_t { } error_tag { };
238
239 template<class T, std::enable_if_t<std::is_trivially_destructible<T>::value>* = nullptr> void destroy(T&) { }
240 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(); }
241
242 template<class T, class E>
243 union constexpr_storage {
244     typedef T value_type;
245     typedef E error_type;
246     typedef unexpected<E> unexpected_type;
247     char dummy;
248     value_type val;
249     error_type err;
250     constexpr constexpr_storage() : dummy() { }
251     constexpr constexpr_storage(value_tag_t) : val() { }
252     constexpr constexpr_storage(error_tag_t) : err() { }
253     constexpr constexpr_storage(value_tag_t, const value_type& v) : val(v) { }
254     constexpr constexpr_storage(error_tag_t, const error_type& e) : err(e) { }
255     ~constexpr_storage() = default;
256 };
257
258 template<class T, class E>
259 union storage {
260     typedef T value_type;
261     typedef E error_type;
262     typedef unexpected<E> unexpected_type;
263     char dummy;
264     value_type val;
265     error_type err;
266     constexpr storage() : dummy() { }
267     constexpr storage(value_tag_t) : val() { }
268     constexpr storage(error_tag_t) : err() { }
269     constexpr storage(value_tag_t, const value_type& val) : val(val) { }
270     constexpr storage(value_tag_t, value_type&& val) : val(std::forward<value_type>(val)) { }
271     constexpr storage(error_tag_t, const error_type& err) : err(err) { }
272     constexpr storage(error_tag_t, error_type&& err) : err(std::forward<error_type>(err)) { }
273     ~storage() { }
274 };
275
276 template<class E>
277 union constexpr_storage<void, E> {
278     typedef void value_type;
279     typedef E error_type;
280     typedef unexpected<E> unexpected_type;
281     char dummy;
282     error_type err;
283     constexpr constexpr_storage() : dummy() { }
284     constexpr constexpr_storage(value_tag_t) : dummy() { }
285     constexpr constexpr_storage(error_tag_t) : err() { }
286     constexpr constexpr_storage(error_tag_t, const error_type& e) : err(e) { }
287     ~constexpr_storage() = default;
288 };
289
290 template<class E>
291 union storage<void, E> {
292     typedef void value_type;
293     typedef E error_type;
294     typedef unexpected<E> unexpected_type;
295     char dummy;
296     error_type err;
297     constexpr storage() : dummy() { }
298     constexpr storage(value_tag_t) : dummy() { }
299     constexpr storage(error_tag_t) : err() { }
300     constexpr storage(error_tag_t, const error_type& err) : err(err) { }
301     constexpr storage(error_tag_t, error_type&& err) : err(std::forward<error_type>(err)) { }
302     ~storage() { }
303 };
304
305 template<class T, class E>
306 struct constexpr_base {
307     typedef T value_type;
308     typedef E error_type;
309     typedef unexpected<E> unexpected_type;
310     constexpr_storage<value_type, error_type> s;
311     bool has;
312     constexpr constexpr_base() : s(), has(true) { }
313     constexpr constexpr_base(value_tag_t tag) : s(tag), has(true) { }
314     constexpr constexpr_base(error_tag_t tag) : s(tag), has(false) { }
315     constexpr constexpr_base(value_tag_t tag, const value_type& val) : s(tag, val), has(true) { }
316     constexpr constexpr_base(error_tag_t tag, const error_type& err) : s(tag, err), has(false) { }
317     ~constexpr_base() = default;
318 };
319
320 template<class T, class E>
321 struct base {
322     typedef T value_type;
323     typedef E error_type;
324     typedef unexpected<E> unexpected_type;
325     storage<value_type, error_type> s;
326     bool has;
327     constexpr base() : s(), has(true) { }
328     constexpr base(value_tag_t tag) : s(tag), has(true) { }
329     constexpr base(error_tag_t tag) : s(tag), has(false) { }
330     constexpr base(value_tag_t tag, const value_type& val) : s(tag, val), has(true) { }
331     constexpr base(value_tag_t tag, value_type&& val) : s(tag, std::forward<value_type>(val)), has(true) { }
332     constexpr base(error_tag_t tag, const error_type& err) : s(tag, err), has(false) { }
333     constexpr base(error_tag_t tag, error_type&& err) : s(tag, std::forward<error_type>(err)), has(false) { }
334     base(const base& o)
335         : has(o.has)
336     {
337         if (has)
338             ::new (&s.val) value_type(o.s.val);
339         else
340             ::new (&s.err) error_type(o.s.err);
341     }
342     base(base&& o)
343         : has(o.has)
344     {
345         if (has)
346             ::new (&s.val) value_type(std::move(o.s.val));
347         else
348             ::new (&s.err) error_type(std::move(o.s.err));
349     }
350     ~base()
351     {
352         if (has)
353             destroy(s.val);
354         else
355             destroy(s.err);
356     }
357 };
358
359 template<class E>
360 struct constexpr_base<void, E> {
361     typedef void value_type;
362     typedef E error_type;
363     typedef unexpected<E> unexpected_type;
364     constexpr_storage<value_type, error_type> s;
365     bool has;
366     constexpr constexpr_base() : s(), has(true) { }
367     constexpr constexpr_base(value_tag_t tag) : s(tag), has(true) { }
368     constexpr constexpr_base(error_tag_t tag) : s(tag), has(false) { }
369     constexpr constexpr_base(error_tag_t tag, const error_type& err) : s(tag, err), has(false) { }
370     constexpr constexpr_base(error_tag_t tag, error_type&& err) : s(tag, std::forward<error_type>(err)), has(false) { }
371     ~constexpr_base() = default;
372 };
373
374 template<class E>
375 struct base<void, E> {
376     typedef void value_type;
377     typedef E error_type;
378     typedef unexpected<E> unexpected_type;
379     storage<value_type, error_type> s;
380     bool has;
381     constexpr base() : s(), has(true) { }
382     constexpr base(value_tag_t tag) : s(tag), has(true) { }
383     constexpr base(error_tag_t tag) : s(tag), has(false) { }
384     constexpr base(error_tag_t tag, const error_type& err) : s(tag, err), has(false) { }
385     constexpr base(error_tag_t tag, error_type&& err) : s(tag, std::forward<error_type>(err)), has(false) { }
386     base(const base& o)
387         : has(o.has)
388     {
389         if (!has)
390             ::new (&s.err) error_type(o.s.err);
391     }
392     base(base&& o)
393         : has(o.has)
394     {
395         if (!has)
396             ::new (&s.err) error_type(std::move(o.s.err));
397     }
398     ~base()
399     {
400         if (!has)
401             destroy(s.err);
402     }
403 };
404
405 template<class T, class E>
406 using base_select = typename std::conditional<
407     ((std::is_void<T>::value || std::is_trivially_destructible<T>::value)
408         && std::is_trivially_destructible<E>::value),
409     constexpr_base<typename std::remove_const<T>::type, typename std::remove_const<E>::type>,
410     base<typename std::remove_const<T>::type, typename std::remove_const<E>::type>
411 >::type;
412
413 } // namespace __expected_detail
414
415 template<class T, class E>
416 class expected : private __expected_detail::base_select<T, E> {
417     typedef __expected_detail::base_select<T, E> base;
418
419 public:
420     typedef typename base::value_type value_type;
421     typedef typename base::error_type error_type;
422     typedef typename base::unexpected_type unexpected_type;
423
424 private:
425     typedef expected<value_type, error_type> type;
426
427 public:
428     template<class U> struct rebind {
429         using type = expected<U, error_type>;
430     };
431
432     constexpr expected() : base(__expected_detail::value_tag) { }
433     expected(const expected&) = default;
434     expected(expected&&) = default;
435
436     constexpr expected(const value_type& e) : base(__expected_detail::value_tag, e) { }
437     constexpr expected(value_type&& e) : base(__expected_detail::value_tag, std::forward<value_type>(e)) { }
438     template<class... Args> constexpr explicit expected(std::in_place_t, Args&&... args) : base(__expected_detail::value_tag, value_type(std::forward<Args>(args)...)) { }
439     // template<class U, class... Args> constexpr explicit expected(in_place_t, std::initializer_list<U>, Args&&...);
440     constexpr expected(const unexpected_type& u) : base(__expected_detail::error_tag, u.value()) { }
441     constexpr expected(unexpected_type&& u) : base(__expected_detail::error_tag, std::forward<unexpected_type>(u).value()) { }
442     template<class Err> constexpr expected(const unexpected<Err>& u) : base(__expected_detail::error_tag, u.value()) { }
443     template<class Err> constexpr expected(unexpected<Err>&& u) : base(__expected_detail::error_tag, std::forward<Err>(u.value())) { }
444     template<class... Args> constexpr explicit expected(unexpected_t, Args&&... args) : base(__expected_detail::value_tag, unexpected_type(std::forward<Args>(args)...)) { }
445     // template<class U, class... Args> constexpr explicit expected(unexpected_t, std::initializer_list<U>, Args&&...);
446
447     ~expected() = default;
448
449     expected& operator=(const expected& e) { type(e).swap(*this); return *this; }
450     expected& operator=(expected&& e) { type(std::move(e)).swap(*this); return *this; }
451     template<class U> expected& operator=(U&& u) { type(std::move(u)).swap(*this); return *this; }
452     expected& operator=(const unexpected_type& u) { type(u).swap(*this); return *this; }
453     expected& operator=(unexpected_type&& u) { type(std::move(u)).swap(*this); return *this; }
454     // template<class... Args> void emplace(Args&&...);
455     // template<class U, class... Args> void emplace(std::initializer_list<U>, Args&&...);
456
457     void swap(expected& o)
458     {
459         using std::swap;
460         if (base::has && o.has)
461             swap(base::s.val, o.s.val);
462         else if (base::has && !o.has) {
463             error_type e(std::move(o.s.err));
464             __expected_detail::destroy(o.s.err);
465             ::new (&o.s.val) value_type(std::move(base::s.val));
466             __expected_detail::destroy(base::s.val);
467             ::new (&base::s.err) error_type(std::move(e));
468             swap(base::has, o.has);
469         } else if (!base::has && o.has) {
470             value_type v(std::move(o.s.val));
471             __expected_detail::destroy(o.s.val);
472             ::new (&o.s.err) error_type(std::move(base::s.err));
473             __expected_detail::destroy(base::s.err);
474             ::new (&base::s.val) value_type(std::move(v));
475             swap(base::has, o.has);
476         } else
477             swap(base::s.err, o.s.err);
478     }
479
480     constexpr const value_type* operator->() const { return &base::s.val; }
481     value_type* operator->() { return &base::s.val; }
482     constexpr const value_type& operator*() const & { return base::s.val; }
483     value_type& operator*() & { return base::s.val; }
484     constexpr const value_type&& operator*() const && { return std::move(base::s.val); }
485     constexpr value_type&& operator*() && { return std::move(base::s.val); }
486     constexpr explicit operator bool() const { return base::has; }
487     constexpr bool has_value() const { return base::has; }
488     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); }
489     constexpr value_type& value() & { return base::has ? base::s.val : (__EXPECTED_THROW(bad_expected_access<error_type>(base::s.err)), base::s.val); }
490     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)); }
491     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)); }
492     constexpr const error_type& error() const & { return !base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err); }
493     error_type& error() & { return !base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err); }
494     constexpr error_type&& error() && { return std::move(!base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err)); }
495     constexpr const error_type&& error() const && { return std::move(!base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err)); }
496     template<class U> constexpr value_type value_or(U&& u) const & { return base::has ? **this : static_cast<value_type>(std::forward<U>(u)); }
497     template<class U> value_type value_or(U&& u) && { return base::has ? std::move(**this) : static_cast<value_type>(std::forward<U>(u)); }
498 };
499
500 template<class E>
501 class expected<void, E> : private __expected_detail::base_select<void, E> {
502     typedef __expected_detail::base_select<void, E> base;
503
504 public:
505     typedef typename base::value_type value_type;
506     typedef typename base::error_type error_type;
507     typedef typename base::unexpected_type unexpected_type;
508
509 private:
510     typedef expected<value_type, error_type> type;
511
512 public:
513     template<class U> struct rebind {
514         using type = expected<U, error_type>;
515     };
516
517     constexpr expected() : base(__expected_detail::value_tag) { }
518     expected(const expected&) = default;
519     expected(expected&&) = default;
520     // constexpr explicit expected(in_place_t);
521     constexpr expected(unexpected_type const& u) : base(__expected_detail::error_tag, u.value()) { }
522     constexpr expected(unexpected_type&& u) : base(__expected_detail::error_tag, std::forward<unexpected_type>(u).value()) { }
523     template<class Err> constexpr expected(unexpected<Err> const& u) : base(__expected_detail::error_tag, u.value()) { }
524
525     ~expected() = default;
526
527     expected& operator=(const expected& e) { type(e).swap(*this); return *this; }
528     expected& operator=(expected&& e) { type(std::move(e)).swap(*this); return *this; }
529     expected& operator=(const unexpected_type& u) { type(u).swap(*this); return *this; } // Not in the current paper.
530     expected& operator=(unexpected_type&& u) { type(std::move(u)).swap(*this); return *this; } // Not in the current paper.
531     // void emplace();
532
533     void swap(expected& o)
534     {
535         using std::swap;
536         if (base::has && o.has) {
537             // Do nothing.
538         } else if (base::has && !o.has) {
539             error_type e(std::move(o.s.err));
540             ::new (&base::s.err) error_type(e);
541             swap(base::has, o.has);
542         } else if (!base::has && o.has) {
543             ::new (&o.s.err) error_type(std::move(base::s.err));
544             swap(base::has, o.has);
545         } else
546             swap(base::s.err, o.s.err);
547     }
548
549     constexpr explicit operator bool() const { return base::has; }
550     constexpr bool has_value() const { return base::has; }
551     void value() const { !base::has ? __EXPECTED_THROW(bad_expected_access<void>()) : void(); }
552     constexpr const E& error() const & { return !base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err); }
553     E& error() & { return !base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err); }
554     constexpr E&& error() && { return std::move(!base::has ? base::s.err : (__EXPECTED_THROW(bad_expected_access<void>()), base::s.err)); }
555 };
556
557 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()); }
558 template<class T, class E> constexpr bool operator!=(const expected<T, E>& x, const expected<T, E>& y) { return !(x == y); }
559
560 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()); }
561
562 template<class T, class E> constexpr bool operator==(const expected<T, E>& x, const T& y) { return x == expected<T, E>(y); }
563 template<class T, class E> constexpr bool operator==(const T& x, const expected<T, E>& y) { return expected<T, E>(x) == y; }
564 template<class T, class E> constexpr bool operator!=(const expected<T, E>& x, const T& y) { return x != expected<T, E>(y); }
565 template<class T, class E> constexpr bool operator!=(const T& x, const expected<T, E>& y) { return expected<T, E>(x) != y; }
566
567 template<class T, class E> constexpr bool operator==(const expected<T, E>& x, const unexpected<E>& y) { return x == expected<T, E>(y); }
568 template<class T, class E> constexpr bool operator==(const unexpected<E>& x, const expected<T, E>& y) { return expected<T, E>(x) == y; }
569 template<class T, class E> constexpr bool operator!=(const expected<T, E>& x, const unexpected<E>& y) { return x != expected<T, E>(y); }
570 template<class T, class E> constexpr bool operator!=(const unexpected<E>& x, const expected<T, E>& y) { return expected<T, E>(x) != y; }
571
572 template<typename T, typename E> void swap(expected<T, E>& x, expected<T, E>& y) { x.swap(y); }
573
574 }}} // namespace std::experimental::fundamentals_v3
575
576 __EXPECTED_INLINE_VARIABLE constexpr std::experimental::unexpected_t& unexpect = std::experimental::unexpect;
577 template<class T, class E> using Expected = std::experimental::expected<T, E>;