[WTF] Import std::optional reference implementation as WTF::Optional
[WebKit-https.git] / Source / WTF / wtf / Expected.h
1 /*
2  * Copyright (C) 2016 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 // WTF::Expected is based on std::expected, as described here: http://wg21.link/p0323r1
27 // The specification expects to throw. This implementation doesn't support exceptions, uses RELEASE_ASSERT instead.
28
29 #pragma once
30
31 #include <cstdlib>
32 #include <functional>
33 #include <initializer_list>
34 #include <type_traits>
35 #include <utility>
36 #include <wtf/Assertions.h>
37 #include <wtf/Compiler.h>
38 #include <wtf/Optional.h>
39 #include <wtf/StdLibExtras.h>
40
41 namespace WTF {
42
43 template <class E>
44 class UnexpectedType {
45 public:
46     UnexpectedType() = delete;
47     constexpr explicit UnexpectedType(const E& e) : val(e) { }
48     constexpr explicit UnexpectedType(E&& e) : val(WTFMove(e)) { }
49     constexpr const E& value() const { return val; }
50     RELAXED_CONSTEXPR E& value() { return val; }
51
52 private:
53     E val;
54 };
55
56 template <class E> constexpr bool operator==(const UnexpectedType<E>& lhs, const UnexpectedType<E>& rhs) { return lhs.value() == rhs.value(); }
57 template <class E> constexpr bool operator!=(const UnexpectedType<E>& lhs, const UnexpectedType<E>& rhs) { return lhs.value() != rhs.value(); }
58 template <class E> constexpr bool operator<(const UnexpectedType<E>& lhs, const UnexpectedType<E>& rhs) { return lhs.value() < rhs.value(); }
59 template <class E> constexpr bool operator>(const UnexpectedType<E>& lhs, const UnexpectedType<E>& rhs) { return lhs.value() > rhs.value(); }
60 template <class E> constexpr bool operator<=(const UnexpectedType<E>& lhs, const UnexpectedType<E>& rhs) { return lhs.value() <= rhs.value(); }
61 template <class E> constexpr bool operator>=(const UnexpectedType<E>& lhs, const UnexpectedType<E>& rhs) { return lhs.value() >= rhs.value(); }
62
63 template <class E> constexpr UnexpectedType<std::decay_t<E>> makeUnexpected(E&& v) { return UnexpectedType<typename std::decay<E>::type>(std::forward<E>(v)); }
64
65 struct UnexpectTag {
66     UnexpectTag() = delete;
67 };
68 constexpr UnexpectTag Unexpect { };
69
70 namespace ExpectedDetail {
71
72 // Invoked where std::Expected would instead throw.
73 inline NO_RETURN_DUE_TO_CRASH void Throw() { RELEASE_ASSERT_NOT_REACHED(); }
74
75 static constexpr enum class ValueTagType { } ValueTag { };
76 static constexpr enum class ErrorTagType { } ErrorTag { };
77
78 template<class T, std::enable_if_t<std::is_trivially_destructible<T>::value>* = nullptr> void destroy(T& t) { }
79 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(); }
80
81 template <class T, class E>
82 union ConstexprStorage {
83     typedef T ValueType;
84     typedef E ErrorType;
85     char dummy;
86     ValueType val;
87     ErrorType err;
88     constexpr ConstexprStorage() : dummy() { }
89     constexpr ConstexprStorage(ValueTagType) : val() { }
90     constexpr ConstexprStorage(ErrorTagType) : err() { }
91     constexpr ConstexprStorage(ValueTagType, const ValueType& v) : val(v) { }
92     constexpr ConstexprStorage(ErrorTagType, const ErrorType& e) : err(e) { }
93     ~ConstexprStorage() = default;
94 };
95
96 template <class T, class E>
97 union Storage {
98     typedef T ValueType;
99     typedef E ErrorType;
100     char dummy;
101     ValueType val;
102     ErrorType err;
103     constexpr Storage() : dummy() { }
104     constexpr Storage(ValueTagType) : val() { }
105     constexpr Storage(ErrorTagType) : err() { }
106     constexpr Storage(ValueTagType, const ValueType& val) : val(val) { }
107     constexpr Storage(ErrorTagType, const ErrorType& err) : err(err) { }
108     ~Storage() { }
109 };
110
111 template <class E>
112 union ConstexprStorage<void, E> {
113     typedef void ValueType;
114     typedef E ErrorType;
115     char dummy;
116     ErrorType err;
117     constexpr ConstexprStorage() : dummy() { }
118     constexpr ConstexprStorage(ValueTagType) : dummy() { }
119     constexpr ConstexprStorage(ErrorTagType) : err() { }
120     constexpr ConstexprStorage(ErrorTagType, const ErrorType& e) : err(e) { }
121     ~ConstexprStorage() = default;
122 };
123
124 template <class E>
125 union Storage<void, E> {
126     typedef void ValueType;
127     typedef E ErrorType;
128     char dummy;
129     ErrorType err;
130     constexpr Storage() : dummy() { }
131     constexpr Storage(ValueTagType) : dummy() { }
132     constexpr Storage(ErrorTagType) : err() { }
133     constexpr Storage(ErrorTagType, const ErrorType& err) : err(err) { }
134     ~Storage() { }
135 };
136
137 template <class T, class E>
138 struct ConstexprBase {
139     typedef T ValueType;
140     typedef E ErrorType;
141     ConstexprStorage<ValueType, ErrorType> s;
142     bool has;
143     constexpr ConstexprBase() : s(), has(true) { }
144     constexpr ConstexprBase(ValueTagType tag) : s(tag), has(true) { }
145     constexpr ConstexprBase(ErrorTagType tag) : s(tag), has(false) { }
146     constexpr ConstexprBase(ValueTagType tag, const ValueType& val) : s(tag, val), has(true) { }
147     constexpr ConstexprBase(ErrorTagType tag, const ErrorType& err) : s(tag, err), has(false) { }
148     ~ConstexprBase() = default;
149 };
150
151 template <class T, class E>
152 struct Base {
153     typedef T ValueType;
154     typedef E ErrorType;
155     Storage<ValueType, ErrorType> s;
156     bool has;
157     constexpr Base() : s(), has(true) { }
158     constexpr Base(ValueTagType tag) : s(tag), has(true) { }
159     constexpr Base(ErrorTagType tag) : s(tag), has(false) { }
160     constexpr Base(ValueTagType tag, const ValueType& val) : s(tag, val), has(true) { }
161     constexpr Base(ErrorTagType tag, const ErrorType& err) : s(tag, err), has(false) { }
162     Base(const Base& o)
163         : has(o.has)
164     {
165         if (has)
166             ::new (&s.val) ValueType(o.s.val);
167         else
168             ::new (&s.err) ErrorType(o.s.err);
169     }
170     Base(Base&& o)
171         : has(o.has)
172     {
173         if (has)
174             ::new (&s.val) ValueType(WTFMove(o.s.val));
175         else
176             ::new (&s.err) ErrorType(WTFMove(o.s.err));
177     }
178     ~Base()
179     {
180         if (has)
181             destroy(s.val);
182         else
183             destroy(s.err);
184     }
185 };
186
187 template <class E>
188 struct ConstexprBase<void, E> {
189     typedef void ValueType;
190     typedef E ErrorType;
191     ConstexprStorage<ValueType, ErrorType> s;
192     bool has;
193     constexpr ConstexprBase() : s(), has(true) { }
194     constexpr ConstexprBase(ValueTagType tag) : s(tag), has(true) { }
195     constexpr ConstexprBase(ErrorTagType tag) : s(tag), has(false) { }
196     constexpr ConstexprBase(ErrorTagType tag, const ErrorType& err) : s(tag, err), has(false) { }
197     ~ConstexprBase() = default;
198 };
199
200 template <class E>
201 struct Base<void, E> {
202     typedef void ValueType;
203     typedef E ErrorType;
204     Storage<ValueType, ErrorType> s;
205     bool has;
206     constexpr Base() : s(), has(true) { }
207     constexpr Base(ValueTagType tag) : s(tag), has(true) { }
208     constexpr Base(ErrorTagType tag) : s(tag), has(false) { }
209     constexpr Base(ErrorTagType tag, const ErrorType& err) : s(tag, err), has(false) { }
210     Base(const Base& o)
211         : has(o.has)
212     {
213         if (!has)
214             ::new (&s.err) ErrorType(o.s.err);
215     }
216     Base(Base&& o)
217         : has(o.has)
218     {
219         if (!has)
220             ::new (&s.err) ErrorType(WTFMove(o.s.err));
221     }
222     ~Base()
223     {
224         if (!has)
225             destroy(s.err);
226     }
227 };
228
229 template <class T, class E>
230 using BaseSelect = typename std::conditional<
231     ((std::is_void<T>::value || std::is_trivially_destructible<T>::value)
232         && std::is_trivially_destructible<E>::value),
233     ConstexprBase<typename std::remove_const<T>::type, typename std::remove_const<E>::type>,
234     Base<typename std::remove_const<T>::type, typename std::remove_const<E>::type>
235 >::type;
236
237 } // namespace ExpectedDetail
238
239 template <class T, class E>
240 class Expected : private ExpectedDetail::BaseSelect<T, E> {
241     typedef ExpectedDetail::BaseSelect<T, E> base;
242
243 public:
244     typedef typename base::ValueType ValueType;
245     typedef typename base::ErrorType ErrorType;
246
247 private:
248     typedef Expected<ValueType, ErrorType> type;
249
250 public:
251     // template <class U> struct rebind { using type = Expected<U, ErrorType>; };
252
253     constexpr Expected() : base(ExpectedDetail::ValueTag) { }
254     Expected(const Expected&) = default;
255     Expected(Expected&&) = default;
256     constexpr Expected(const ValueType& e) : base(ExpectedDetail::ValueTag, e) { }
257     constexpr Expected(ValueType&& e) : base(ExpectedDetail::ValueTag, WTFMove(e)) { }
258     // template <class... Args> constexpr explicit Expected(in_place_t, Args&&...);
259     // template <class U, class... Args> constexpr explicit Expected(in_place_t, std::initializer_list<U>, Args&&...);
260     constexpr Expected(UnexpectedType<ErrorType> const& u) : base(ExpectedDetail::ErrorTag, u.value()) { }
261     template <class Err> constexpr Expected(UnexpectedType<Err> const& u) : base(ExpectedDetail::ErrorTag, u.value()) { }
262     // template <class... Args> constexpr explicit Expected(UnexpectTag, Args&&...);
263     // template <class U, class... Args> constexpr explicit Expected(UnexpectTag, std::initializer_list<U>, Args&&...);
264
265     ~Expected() = default;
266
267     Expected& operator=(const Expected& e) { type(e).swap(*this); return *this; }
268     Expected& operator=(Expected&& e) { type(WTFMove(e)).swap(*this); return *this; }
269     template <class U> Expected& operator=(U&& u) { type(WTFMove(u)).swap(*this); return *this; }
270     Expected& operator=(const UnexpectedType<ErrorType>& u) { type(u).swap(*this); return *this; }
271     Expected& operator=(UnexpectedType<ErrorType>&& u) { type(WTFMove(u)).swap(*this); return *this; }
272     // template <class... Args> void emplace(Args&&...);
273     // template <class U, class... Args> void emplace(std::initializer_list<U>, Args&&...);
274
275     void swap(Expected& o)
276     {
277         using std::swap;
278         if (base::has && o.has)
279             swap(base::s.val, o.s.val);
280         else if (base::has && !o.has) {
281             ErrorType e(WTFMove(o.s.err));
282             ::new (&o.s.val) ValueType(WTFMove(base::s.val));
283             ::new (&base::s.err) ErrorType(e);
284             swap(base::has, o.has);
285         } else if (!base::has && o.has) {
286             ValueType v(WTFMove(o.s.val));
287             ::new (&o.s.err) ErrorType(WTFMove(base::s.err));
288             ::new (&base::s.val) ValueType(v);
289             swap(base::has, o.has);
290         } else
291             swap(base::s.err, o.s.err);
292     }
293
294     constexpr const ValueType* operator->() const { return &base::s.val; }
295     ValueType* operator->() { return &base::s.val; }
296     constexpr const ValueType& operator*() const & { return base::s.val; }
297     ValueType& operator*() & { return base::s.val; }
298     constexpr const ValueType&& operator*() const && { return WTFMove(base::s.val); }
299     RELAXED_CONSTEXPR ValueType&& operator*() && { return WTFMove(base::s.val); }
300     constexpr explicit operator bool() const { return base::has; }
301     constexpr bool hasValue() const { return base::has; }
302     constexpr const ValueType& value() const & { return base::has ? base::s.val : (ExpectedDetail::Throw(), base::s.val); }
303     RELAXED_CONSTEXPR ValueType& value() & { return base::has ? base::s.val : (ExpectedDetail::Throw(), base::s.val); }
304     constexpr const ValueType&& value() const && { return base::has ? base::s.val : (ExpectedDetail::Throw(), base::s.val); }
305     RELAXED_CONSTEXPR ValueType&& value() && { return base::has ? base::s.val : (ExpectedDetail::Throw(), base::s.val); }
306     constexpr const ErrorType& error() const & { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); }
307     ErrorType& error() & { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); }
308     RELAXED_CONSTEXPR ErrorType&& error() && { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); }
309     constexpr const ErrorType&& error() const && { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); }
310     constexpr UnexpectedType<ErrorType> getUnexpected() const { return UnexpectedType<ErrorType>(base::s.err); }
311     template <class U> constexpr ValueType valueOr(U&& u) const & { return base::has ? **this : static_cast<ValueType>(std::forward<U>(u)); }
312     template <class U> ValueType valueOr(U&& u) && { return base::has ? WTFMove(**this) : static_cast<ValueType>(std::forward<U>(u)); }
313 };
314
315 template <class E>
316 class Expected<void, E> : private ExpectedDetail::BaseSelect<void, E> {
317     typedef ExpectedDetail::BaseSelect<void, E> base;
318
319 public:
320     typedef typename base::ValueType ValueType;
321     typedef typename base::ErrorType ErrorType;
322
323 private:
324     typedef Expected<ValueType, ErrorType> type;
325
326 public:
327     // template <class U> struct rebind { typedef Expected<U, ErrorType> type; };
328
329     constexpr Expected() : base(ExpectedDetail::ValueTag) { }
330     Expected(const Expected&) = default;
331     Expected(Expected&&) = default;
332     // constexpr explicit Expected(in_place_t);
333     constexpr Expected(UnexpectedType<E> const& u) : base(ExpectedDetail::ErrorTag, u.value()) { }
334     template <class Err> constexpr Expected(UnexpectedType<Err> const& u) : base(ExpectedDetail::ErrorTag, u.value()) { }
335
336     ~Expected() = default;
337
338     Expected& operator=(const Expected& e) { type(e).swap(*this); return *this; }
339     Expected& operator=(Expected&& e) { type(WTFMove(e)).swap(*this); return *this; }
340     Expected& operator=(const UnexpectedType<E>& u) { type(u).swap(*this); return *this; } // Not in the current paper.
341     Expected& operator=(UnexpectedType<E>&& u) { type(WTFMove(u)).swap(*this); return *this; } // Not in the current paper.
342     // void emplace();
343
344     void swap(Expected& o)
345     {
346         using std::swap;
347         if (base::has && o.has) {
348             // Do nothing.
349         } else if (base::has && !o.has) {
350             ErrorType e(WTFMove(o.s.err));
351             ::new (&base::s.err) ErrorType(e);
352             swap(base::has, o.has);
353         } else if (!base::has && o.has) {
354             ::new (&o.s.err) ErrorType(WTFMove(base::s.err));
355             swap(base::has, o.has);
356         } else
357             swap(base::s.err, o.s.err);
358     }
359
360     constexpr explicit operator bool() const { return base::has; }
361     constexpr bool hasValue() const { return base::has; }
362     void value() const { !base::has ? ExpectedDetail::Throw() : void(); }
363     constexpr const E& error() const & { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); }
364     E& error() & { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); } // Not in the current paper.
365     RELAXED_CONSTEXPR E&& error() && { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); }
366     constexpr const E&& error() const && { return !base::has ? base::s.err : (ExpectedDetail::Throw(), base::s.err); } // Not in the current paper.
367     // constexpr E& error() &;
368     constexpr UnexpectedType<E> getUnexpected() const { return UnexpectedType<E>(base::s.err); }
369 };
370
371 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()); }
372 template <class T, class E> constexpr bool operator!=(const Expected<T, E>& x, const Expected<T, E>& y) { return !(x == y); }
373 template <class T, class E> constexpr bool operator<(const Expected<T, E>& x, const Expected<T, E>& y) { return (!bool(x) && bool(y)) ? false : ((bool(x) && !bool(y)) ? true : ((bool(x) && bool(y)) ? x.value() < y.value() : x.error() < y.error())); }
374 template <class T, class E> constexpr bool operator>(const Expected<T, E>& x, const Expected<T, E>& y) { return !(x == y) && !(x < y); }
375 template <class T, class E> constexpr bool operator<=(const Expected<T, E>& x, const Expected<T, E>& y) { return (x == y) || (x < y); }
376 template <class T, class E> constexpr bool operator>=(const Expected<T, E>& x, const Expected<T, E>& y) { return (x == y) || (x > y); }
377
378 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()); } // Not in the current paper.
379 template <class E> constexpr bool operator<(const Expected<void, E>& x, const Expected<void, E>& y) { return (!bool(x) && bool(y)) ? false : ((bool(x) && !bool(y)) ? true : ((bool(x) && bool(y)) ? false : x.error() < y.error())); } // Not in the current paper.
380
381 template <class T, class E> constexpr bool operator==(const Expected<T, E>& x, const T& y) { return x == Expected<T, E>(y); }
382 template <class T, class E> constexpr bool operator==(const T& x, const Expected<T, E>& y) { return Expected<T, E>(x) == y; }
383 template <class T, class E> constexpr bool operator!=(const Expected<T, E>& x, const T& y) { return x != Expected<T, E>(y); }
384 template <class T, class E> constexpr bool operator!=(const T& x, const Expected<T, E>& y) { return Expected<T, E>(x) != y; }
385 template <class T, class E> constexpr bool operator<(const Expected<T, E>& x, const T& y) { return x < Expected<T, E>(y); }
386 template <class T, class E> constexpr bool operator<(const T& x, const Expected<T, E>& y) { return Expected<T, E>(x) < y; }
387 template <class T, class E> constexpr bool operator<=(const Expected<T, E>& x, const T& y) { return x <= Expected<T, E>(y); }
388 template <class T, class E> constexpr bool operator<=(const T& x, const Expected<T, E>& y) { return Expected<T, E>(x) <= y; }
389 template <class T, class E> constexpr bool operator>(const Expected<T, E>& x, const T& y) { return x > Expected<T, E>(y); }
390 template <class T, class E> constexpr bool operator>(const T& x, const Expected<T, E>& y) { return Expected<T, E>(x) > y; }
391 template <class T, class E> constexpr bool operator>=(const Expected<T, E>& x, const T& y) { return x >= Expected<T, E>(y); }
392 template <class T, class E> constexpr bool operator>=(const T& x, const Expected<T, E>& y) { return Expected<T, E>(x) >= y; }
393
394 template <class T, class E> constexpr bool operator==(const Expected<T, E>& x, const UnexpectedType<E>& y) { return x == Expected<T, E>(y); }
395 template <class T, class E> constexpr bool operator==(const UnexpectedType<E>& x, const Expected<T, E>& y) { return Expected<T, E>(x) == y; }
396 template <class T, class E> constexpr bool operator!=(const Expected<T, E>& x, const UnexpectedType<E>& y) { return x != Expected<T, E>(y); }
397 template <class T, class E> constexpr bool operator!=(const UnexpectedType<E>& x, const Expected<T, E>& y) { return Expected<T, E>(x) != y; }
398 template <class T, class E> constexpr bool operator<(const Expected<T, E>& x, const UnexpectedType<E>& y) { return x < Expected<T, E>(y); }
399 template <class T, class E> constexpr bool operator<(const UnexpectedType<E>& x, const Expected<T, E>& y) {  return Expected<T, E>(x) < y; }
400 template <class T, class E> constexpr bool operator<=(const Expected<T, E>& x, const UnexpectedType<E>& y) { return x <= Expected<T, E>(y); }
401 template <class T, class E> constexpr bool operator<=(const UnexpectedType<E>& x, const Expected<T, E>& y) { return Expected<T, E>(x) <= y; }
402 template <class T, class E> constexpr bool operator>(const Expected<T, E>& x, const UnexpectedType<E>& y) { return x > Expected<T, E>(y); }
403 template <class T, class E> constexpr bool operator>(const UnexpectedType<E>& x, const Expected<T, E>& y) { return Expected<T, E>(x) > y; }
404 template <class T, class E> constexpr bool operator>=(const Expected<T, E>& x, const UnexpectedType<E>& y) { return x >= Expected<T, E>(y); }
405 template <class T, class E> constexpr bool operator>=(const UnexpectedType<E>& x, const Expected<T, E>& y) { return Expected<T, E>(x) >= y; }
406
407 template <typename T, typename E> void swap(Expected<T, E>& x, Expected<T, E>& y) { x.swap(y); }
408
409 template <class T, class E = std::nullopt_t> constexpr Expected<std::decay_t<T>, E> makeExpected(T&& v)
410 {
411     return Expected<typename std::decay<T>::type, E>(std::forward<T>(v));
412 }
413 template <class T, class E> constexpr Expected<T, std::decay_t<E>> makeExpectedFromError(E&& e) { return Expected<T, std::decay_t<E>>(makeUnexpected(e)); }
414 template <class T, class E, class U> constexpr Expected<T, E> makeExpectedFromError(U&& u) { return Expected<T, E>(makeUnexpected(E { std::forward<U>(u) } )); }
415 // template <class F, class E = std::nullopt_t> constexpr Expected<typename std::result_of<F>::type, E> makeExpected_from_call(F f);
416
417 inline Expected<void, std::nullopt_t> makeExpected() { return Expected<void, std::nullopt_t>(); }
418
419 } // namespace WTF
420
421 namespace std {
422
423 template <class T, class E> struct hash<WTF::Expected<T, E>> {
424     typedef WTF::Expected<T, E> argument_type;
425     typedef std::size_t result_type;
426     result_type operator()(argument_type const& e) const { return e ? hash<typename argument_type::ValueType> { } (e.value()) : hash<typename argument_type::ErrorType> { } (e.error()); }
427 };
428
429 template <class E> struct hash<WTF::Expected<void, E>> {
430     typedef WTF::Expected<void, E> argument_type;
431     typedef std::size_t result_type;
432     result_type operator()(argument_type const& e) const { return e ? 0 : hash<typename argument_type::ErrorType> { } (e.error()); }
433 };
434
435 }
436
437 using WTF::UnexpectedType;
438 using WTF::makeUnexpected;
439 using WTF::Unexpect;
440 using WTF::Expected;
441 using WTF::makeExpected;
442 using WTF::makeExpectedFromError;