• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15 
16 #include <functional>
17 #include <optional>
18 #include <type_traits>
19 #include <utility>
20 #include <variant>
21 
22 namespace pw::internal {
23 
24 // Helper type trait for removing reference and cv-qualification of a type.
25 template <class T>
26 struct remove_cvref {
27   typedef std::remove_cv_t<std::remove_reference_t<T>> type;
28 };
29 
30 // Helper type trait ::type of above struct.
31 template <class T>
32 using remove_cvref_t = typename remove_cvref<T>::type;
33 
34 // Helper type trait for enabling/disabling std::expected constructors.
35 template <class T, class W>
36 constexpr bool converts_from_any_cvref =
37     std::disjunction_v<std::is_constructible<T, W&>,
38                        std::is_convertible<W&, T>,
39                        std::is_constructible<T, W>,
40                        std::is_convertible<W, T>,
41                        std::is_constructible<T, const W&>,
42                        std::is_convertible<const W&, T>,
43                        std::is_constructible<T, const W>,
44                        std::is_convertible<const W, T>>;
45 
46 // Helper type trait for determining if a type is any specialization of a
47 // template class.
48 template <typename T, template <typename...> class Template>
49 constexpr bool is_specialization = false;
50 template <template <typename...> class Template, typename... Ts>
51 constexpr bool is_specialization<Template<Ts...>, Template> = true;
52 
53 // Polyfill implementaion of std::unexpected.
54 
55 template <class E>
56 class unexpected {
57  public:
58   constexpr unexpected(const unexpected&) = default;
59   constexpr unexpected(unexpected&&) = default;
60   template <class Err = E,
61             std::enable_if_t<
62                 !std::is_same_v<remove_cvref_t<Err>, unexpected> &&
63                     !std::is_same_v<remove_cvref_t<Err>, std::in_place_t> &&
64                     std::is_constructible_v<E, Err>,
65                 bool> = true>
unexpected(Err && e)66   constexpr explicit unexpected(Err&& e) : unex_(std::forward<Err>(e)) {}
67   template <class... Args,
68             std::enable_if_t<std::is_constructible_v<E, Args...>, bool> = true>
unexpected(std::in_place_t,Args &&...args)69   constexpr explicit unexpected(std::in_place_t, Args&&... args)
70       : unex_(std::forward<Args>(args)...) {}
71   template <
72       class U,
73       class... Args,
74       std::enable_if_t<std::is_constructible_v<E, std::initializer_list<U>>,
75                        bool> = true>
unexpected(std::in_place_t,std::initializer_list<U> il,Args &&...args)76   constexpr explicit unexpected(std::in_place_t,
77                                 std::initializer_list<U> il,
78                                 Args&&... args)
79       : unex_(il, std::forward<Args>(args)...) {}
80 
81   constexpr unexpected& operator=(const unexpected&) = default;
82   constexpr unexpected& operator=(unexpected&&) = default;
83 
error()84   constexpr const E& error() const& noexcept { return unex_; }
error()85   constexpr E& error() & noexcept { return unex_; }
error()86   constexpr E&& error() && noexcept { return std::move(unex_); }
error()87   constexpr const E&& error() const&& noexcept { return std::move(unex_); }
88 
swap(unexpected & other)89   constexpr void swap(unexpected& other) noexcept(
90       std::is_nothrow_swappable<E>::value) {
91     std::swap(unex_, other.unex_);
92   }
93 
94   template <class E2>
95   friend constexpr bool operator==(const unexpected& x,
96                                    const unexpected<E2>& y) {
97     return x.error() == y.error();
98   }
99 
100  private:
101   E unex_;
102 };
103 
104 // Polyfill implementation of std::unexpect_t and std::unexpect.
105 struct unexpect_t {
106   explicit unexpect_t() = default;
107 };
108 
109 inline constexpr unexpect_t unexpect;
110 
111 template <class T, class E, typename Enable = void>
112 class expected;
113 
114 // Polyfill implementation of std::expected.
115 template <class T, class E>
116 class expected<T, E, std::enable_if_t<!std::is_void_v<T>>> {
117  public:
118   using value_type = T;
119   using error_type = E;
120   using unexpected_type = unexpected<E>;
121 
122   template <class U>
123   using rebind = expected<U, error_type>;
124 
125   template <
126       class Enable = T,
127       std::enable_if_t<std::is_default_constructible_v<Enable>, bool> = true>
expected()128   constexpr expected() : contents_(kInPlaceValue) {}
129   constexpr expected(const expected& rhs) = default;
130   constexpr expected(expected&& rhs) = default;
131   template <
132       class U,
133       class G,
134       // Constraints
135       std::enable_if_t<
136           std::is_constructible_v<T, const U&> &&
137               std::is_constructible_v<E, const G&> &&
138               !converts_from_any_cvref<T, expected<U, G>> &&
139               !std::is_constructible_v<unexpected<E>, expected<U, G>&> &&
140               !std::is_constructible_v<unexpected<E>, expected<U, G>> &&
141               !std::is_constructible_v<unexpected<E>, const expected<U, G>&> &&
142               !std::is_constructible_v<unexpected<E>, const expected<U, G>>,
143           bool> = true,
144       // Explicit
145       std::enable_if_t<!std::is_convertible_v<const U&, T> ||
146                            !std::is_convertible_v<const G&, E>,
147                        bool> = true>
expected(const expected<U,G> & rhs)148   constexpr explicit expected(const expected<U, G>& rhs)
149       : contents_(convert_variant(
150             std::forward<const std::variant<U, G>&>(rhs.contents_))) {}
151   template <
152       class U,
153       class G,
154       // Constraints
155       std::enable_if_t<
156           std::is_constructible_v<T, const U&> &&
157               std::is_constructible_v<E, const G&> &&
158               !converts_from_any_cvref<T, expected<U, G>> &&
159               !std::is_constructible_v<unexpected<E>, expected<U, G>&> &&
160               !std::is_constructible_v<unexpected<E>, expected<U, G>> &&
161               !std::is_constructible_v<unexpected<E>, const expected<U, G>&> &&
162               !std::is_constructible_v<unexpected<E>, const expected<U, G>>,
163           bool> = true,
164       // Explicit
165       std::enable_if_t<std::is_convertible_v<const U&, T> &&
166                            std::is_convertible_v<const G&, E>,
167                        bool> = true>
expected(const expected<U,G> & rhs)168   constexpr /* implicit */ expected(const expected<U, G>& rhs)
169       : contents_(convert_variant(
170             std::forward<const std::variant<U, G>&>(rhs.contents_))) {}
171   template <
172       class U,
173       class G,
174       // Constraints
175       std::enable_if_t<
176           std::is_constructible_v<T, U&&> && std::is_constructible_v<E, G&&> &&
177               !converts_from_any_cvref<T, expected<U, G>> &&
178               !std::is_constructible_v<unexpected<E>, expected<U, G>&> &&
179               !std::is_constructible_v<unexpected<E>, expected<U, G>> &&
180               !std::is_constructible_v<unexpected<E>, const expected<U, G>&> &&
181               !std::is_constructible_v<unexpected<E>, const expected<U, G>>,
182           bool> = true,
183       // Explicit
184       std::enable_if_t<!std::is_convertible_v<U&&, T> ||
185                            !std::is_convertible_v<G&&, E>,
186                        bool> = true>
expected(expected<U,G> && rhs)187   constexpr explicit expected(expected<U, G>&& rhs)
188       : contents_(
189             std::forward<std::variant<U, G>>(convert_variant(rhs.contents_))) {}
190   template <
191       class U,
192       class G,
193       // Constraints
194       std::enable_if_t<
195           std::is_constructible_v<T, U&&> && std::is_constructible_v<E, G&&> &&
196               !converts_from_any_cvref<T, expected<U, G>> &&
197               !std::is_constructible_v<unexpected<E>, expected<U, G>&> &&
198               !std::is_constructible_v<unexpected<E>, expected<U, G>> &&
199               !std::is_constructible_v<unexpected<E>, const expected<U, G>&> &&
200               !std::is_constructible_v<unexpected<E>, const expected<U, G>>,
201           bool> = true,
202       // Explicit
203       std::enable_if_t<std::is_convertible_v<U&&, T> &&
204                            std::is_convertible_v<G&&, E>,
205                        bool> = true>
expected(expected<U,G> && rhs)206   constexpr /* implicit */ expected(expected<U, G>&& rhs)
207       : contents_(
208             convert_variant(std::forward<std::variant<U, G>>(rhs.contents_))) {}
209   template <
210       class U = T,
211       // Constraints
212       std::enable_if_t<!std::is_same_v<remove_cvref_t<U>, std::in_place_t> &&
213                            !std::is_same_v<remove_cvref_t<U>, expected> &&
214                            !is_specialization<U, unexpected> &&
215                            std::is_constructible_v<T, U>,
216                        bool> = true,
217       // Explicit
218       std::enable_if_t<!std::is_convertible_v<U, T>, bool> = true>
expected(U && u)219   constexpr explicit expected(U&& u)
220       : contents_(kInPlaceValue, std::forward<U>(u)) {}
221   template <
222       class U = T,
223       // Constraints
224       std::enable_if_t<!std::is_same_v<remove_cvref_t<U>, std::in_place_t> &&
225                            !std::is_same_v<remove_cvref_t<U>, expected> &&
226                            !is_specialization<U, unexpected> &&
227                            std::is_constructible_v<T, U>,
228                        bool> = true,
229       // Explicit
230       std::enable_if_t<std::is_convertible_v<U, T>, bool> = true>
expected(U && u)231   constexpr /* implicit */ expected(U&& u)
232       : contents_(kInPlaceValue, std::forward<U>(u)) {}
233   template <class G,
234             // Constraints
235             std::enable_if_t<std::is_constructible_v<E, const G&>, bool> = true,
236             // Explicit
237             std::enable_if_t<!std::is_convertible_v<const G&, E>, bool> = true>
expected(const unexpected<G> & e)238   constexpr explicit expected(const unexpected<G>& e)
239       : contents_(kInPlaceError, std::forward<const G&>(e.error())) {}
240   template <class G,
241             // Constraints
242             std::enable_if_t<std::is_constructible_v<E, const G&>, bool> = true,
243             // Explicit
244             std::enable_if_t<std::is_convertible_v<const G&, E>, bool> = true>
expected(const unexpected<G> & e)245   constexpr /* implicit */ expected(const unexpected<G>& e)
246       : contents_(kInPlaceError, std::forward<const G&>(e.error())) {}
247   template <class G,
248             // Constraints
249             std::enable_if_t<std::is_constructible_v<E, G>, bool> = true,
250             // Explicit
251             std::enable_if_t<!std::is_convertible_v<G, E>, bool> = true>
expected(unexpected<G> && e)252   constexpr explicit expected(unexpected<G>&& e)
253       : contents_(kInPlaceError, std::forward<G>(e.error())) {}
254   template <class G,
255             // Constraints
256             std::enable_if_t<std::is_constructible_v<E, G>, bool> = true,
257             // Explicit
258             std::enable_if_t<std::is_convertible_v<G, E>, bool> = true>
expected(unexpected<G> && e)259   constexpr /* implicit */ expected(unexpected<G>&& e)
260       : contents_(kInPlaceError, std::forward<G>(e.error())) {}
261   template <class... Args,
262             std::enable_if_t<std::is_constructible_v<T, Args...>, bool> = true>
expected(std::in_place_t,Args &&...args)263   constexpr explicit expected(std::in_place_t, Args&&... args)
264       : contents_(kInPlaceValue, std::forward<Args>(args)...) {}
265   template <class U,
266             class... Args,
267             std::enable_if_t<
268                 std::is_constructible_v<T, std::initializer_list<U>&, Args...>,
269                 bool> = true>
expected(std::in_place_t,std::initializer_list<U> il,Args &&...args)270   constexpr explicit expected(std::in_place_t,
271                               std::initializer_list<U> il,
272                               Args&&... args)
273       : contents_(kInPlaceValue, il, std::forward<Args>(args)...) {}
274   template <class... Args,
275             std::enable_if_t<std::is_constructible_v<E, Args...>, bool> = true>
expected(unexpect_t,Args &&...args)276   constexpr explicit expected(unexpect_t, Args&&... args)
277       : contents_(kInPlaceError, std::forward<Args>(args)...) {}
278   template <class U,
279             class... Args,
280             std::enable_if_t<
281                 std::is_constructible_v<E, std::initializer_list<U>&, Args...>,
282                 bool> = true>
expected(unexpect_t,std::initializer_list<U> il,Args &&...args)283   constexpr explicit expected(unexpect_t,
284                               std::initializer_list<U> il,
285                               Args&&... args)
286       : contents_(kInPlaceError, il, std::forward<Args>(args)...) {}
287 
288   constexpr expected& operator=(const expected& rhs) = default;
289   constexpr expected& operator=(expected&& rhs) = default;
290   template <
291       class U = T,
292       std::enable_if_t<!std::is_same_v<expected, remove_cvref_t<U>> &&
293                            !is_specialization<remove_cvref_t<U>, unexpected>,
294                        bool> = true>
295   constexpr expected& operator=(U&& u) {
296     value() = std::forward<U>(u);
297   }
298   template <class G>
299   constexpr expected& operator=(const unexpected<G>& e) {
300     error() = std::forward<const G&>(e.error());
301   }
302   template <class G>
303   constexpr expected& operator=(unexpected<G>&& e) {
304     error() = std::forward<G>(e.error());
305   }
306 
307   template <class... Args,
308             std::enable_if_t<std::is_nothrow_constructible_v<T, Args...>,
309                              bool> = true>
emplace(Args &&...args)310   constexpr T& emplace(Args&&... args) noexcept {
311     return contents_.template emplace<kValue>(std::forward<Args>(args)...);
312   }
313   template <
314       class U,
315       class... Args,
316       std::enable_if_t<
317           std::is_nothrow_constructible_v<T, std::initializer_list<U>, Args...>,
318           bool> = true>
emplace(std::initializer_list<U> il,Args &&...args)319   constexpr T& emplace(std::initializer_list<U> il, Args&&... args) noexcept {
320     return contents_.template emplace<kValue>(il, std::forward<Args>(args)...);
321   }
322 
swap(expected & rhs)323   constexpr void swap(expected& rhs) { std::swap(contents_, rhs.contents_); }
324 
325   constexpr T* operator->() noexcept { return std::addressof(value()); }
326   constexpr const T* operator->() const noexcept {
327     return std::addressof(value());
328   }
329   constexpr T& operator*() & noexcept { return value(); }
330   constexpr T&& operator*() && noexcept { return std::move(value()); }
331   constexpr const T& operator*() const& noexcept { return value(); }
332   constexpr const T&& operator*() const&& noexcept {
333     return std::move(value());
334   }
335 
336   constexpr explicit operator bool() const noexcept { return has_value(); }
has_value()337   constexpr bool has_value() const noexcept {
338     return contents_.index() == kValue;
339   }
340 
value()341   constexpr T& value() & { return std::get<kValue>(contents_); }
value()342   constexpr T&& value() && { return std::move(std::get<kValue>(contents_)); }
value()343   constexpr const T& value() const& { return std::get<kValue>(contents_); }
value()344   constexpr const T&& value() const&& {
345     return std::move(std::get<kValue>(contents_));
346   }
347 
error()348   constexpr E& error() & { return std::get<kError>(contents_); }
error()349   constexpr E&& error() && { return std::move(std::get<kError>(contents_)); }
error()350   constexpr const E& error() const& { return std::get<kError>(contents_); }
error()351   constexpr const E&& error() const&& {
352     return std::move(std::get<kError>(contents_));
353   }
354 
355   template <class U>
value_or(U && u)356   constexpr T value_or(U&& u) && {
357     return has_value() ? std::move(value())
358                        : static_cast<T>(std::forward<U>(u));
359   }
360   template <class U>
value_or(U && u)361   constexpr T value_or(U&& u) const& {
362     return has_value() ? value() : static_cast<T>(std::forward<U>(u));
363   }
364 
365   template <class G>
error_or(G && g)366   constexpr E error_or(G&& g) && {
367     return has_value() ? std::forward<G>(g) : std::move(error());
368   }
369   template <class G>
error_or(G && g)370   constexpr E error_or(G&& g) const& {
371     return has_value() ? std::forward<G>(g) : error();
372   }
373 
374   template <class F>
and_then(F && f)375   constexpr auto and_then(F&& f) & {
376     using U = remove_cvref_t<std::invoke_result_t<F, decltype(value())>>;
377     if (has_value()) {
378       return std::invoke(std::forward<F>(f), value());
379     } else {
380       return U(unexpect, error());
381     }
382   }
383   template <class F>
and_then(F && f)384   constexpr auto and_then(F&& f) && {
385     using U = remove_cvref_t<std::invoke_result_t<F, decltype(value())>>;
386     if (has_value()) {
387       return std::invoke(std::forward<F>(f), std::move(value()));
388     } else {
389       return U(unexpect, std::move(error()));
390     }
391   }
392   template <class F>
and_then(F && f)393   constexpr auto and_then(F&& f) const& {
394     using U = remove_cvref_t<std::invoke_result_t<F, decltype(value())>>;
395     if (has_value()) {
396       return std::invoke(std::forward<F>(f), value());
397     } else {
398       return U(unexpect, error());
399     }
400   }
401   template <class F>
and_then(F && f)402   constexpr auto and_then(F&& f) const&& {
403     using U = remove_cvref_t<std::invoke_result_t<F, decltype(value())>>;
404     if (has_value()) {
405       return std::invoke(std::forward<F>(f), std::move(value()));
406     } else {
407       return U(unexpect, std::move(error()));
408     }
409   }
410 
411   template <class F>
or_else(F && f)412   constexpr auto or_else(F&& f) & {
413     using G = remove_cvref_t<std::invoke_result_t<F, decltype(error())>>;
414     if (has_value()) {
415       return G(std::in_place, value());
416     } else {
417       return std::invoke(std::forward<F>(f), error());
418     }
419   }
420   template <class F>
or_else(F && f)421   constexpr auto or_else(F&& f) && {
422     using G = remove_cvref_t<std::invoke_result_t<F, decltype(error())>>;
423     if (has_value()) {
424       return G(std::in_place, value());
425     } else {
426       return std::invoke(std::forward<F>(f), std::move(error()));
427     }
428   }
429   template <class F>
or_else(F && f)430   constexpr auto or_else(F&& f) const& {
431     using G = remove_cvref_t<std::invoke_result_t<F, decltype(error())>>;
432     if (has_value()) {
433       return G(std::in_place, value());
434     } else {
435       return std::invoke(std::forward<F>(f), error());
436     }
437   }
438   template <class F>
or_else(F && f)439   constexpr auto or_else(F&& f) const&& {
440     using G = remove_cvref_t<std::invoke_result_t<F, decltype(error())>>;
441     if (has_value()) {
442       return G(std::in_place, value());
443     } else {
444       return std::invoke(std::forward<F>(f), std::move(error()));
445     }
446   }
447 
448   template <class F>
transform(F && f)449   constexpr auto transform(F&& f) & {
450     using U = std::remove_cv_t<std::invoke_result_t<F, decltype(value())>>;
451     if (has_value()) {
452       return transform_helper<U>(std::forward<F>(f));
453     } else {
454       return expected<U, E>(unexpect, error());
455     }
456   }
457   template <class F>
transform(F && f)458   constexpr auto transform(F&& f) && {
459     using U = std::remove_cv_t<std::invoke_result_t<F, decltype(value())>>;
460     if (has_value()) {
461       return transform_helper<U>(std::forward<F>(f));
462     } else {
463       return expected<U, E>(unexpect, std::move(error()));
464     }
465   }
466   template <class F>
transform(F && f)467   constexpr auto transform(F&& f) const& {
468     using U = std::remove_cv_t<std::invoke_result_t<F, decltype(value())>>;
469     if (has_value()) {
470       return transform_helper<U>(std::forward<F>(f));
471     } else {
472       return expected<U, E>(unexpect, error());
473     }
474   }
475   template <class F>
transform(F && f)476   constexpr auto transform(F&& f) const&& {
477     using U = std::remove_cv_t<std::invoke_result_t<F, decltype(value())>>;
478     if (has_value()) {
479       return transform_helper<U>(std::forward<F>(f));
480     } else {
481       return expected<U, E>(unexpect, std::move(error()));
482     }
483   }
484 
485   template <class F>
transform_error(F && f)486   constexpr auto transform_error(F&& f) & {
487     using G = std::remove_cv_t<std::invoke_result_t<F, decltype(error())>>;
488     if (has_value()) {
489       return expected<T, G>(std::in_place, value());
490     } else {
491       return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), error()));
492     }
493   }
494   template <class F>
transform_error(F && f)495   constexpr auto transform_error(F&& f) && {
496     using G = std::remove_cv_t<std::invoke_result_t<F, decltype(error())>>;
497     if (has_value()) {
498       return expected<T, G>(std::in_place, std::move(value()));
499     } else {
500       return expected<T, G>(
501           unexpect, std::invoke(std::forward<F>(f), std::move(error())));
502     }
503   }
504   template <class F>
transform_error(F && f)505   constexpr auto transform_error(F&& f) const& {
506     using G = std::remove_cv_t<std::invoke_result_t<F, decltype(error())>>;
507     if (has_value()) {
508       return expected<T, G>(std::in_place, value());
509     } else {
510       return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), error()));
511     }
512   }
513   template <class F>
transform_error(F && f)514   constexpr auto transform_error(F&& f) const&& {
515     using G = std::remove_cv_t<std::invoke_result_t<F, decltype(error())>>;
516     if (has_value()) {
517       return expected<T, G>(std::in_place, std::move(value()));
518     } else {
519       return expected<T, G>(
520           unexpect, std::invoke(std::forward<F>(f), std::move(error())));
521     }
522   }
523 
524  private:
525   // Make all specializations of `expected` friends.
526   template <class U, class G, class>
527   friend class expected;
528 
529   static constexpr size_t kValue = 0;
530   static constexpr size_t kError = 1;
531 
532   static constexpr auto kInPlaceValue = std::in_place_index<kValue>;
533   static constexpr auto kInPlaceError = std::in_place_index<kError>;
534 
535   // Helper to convert variant<U, G> -> variant<T, E>
536   template <class U, class G>
convert_variant(const std::variant<U,G> & v)537   std::variant<T, E> convert_variant(const std::variant<U, G>& v) {
538     switch (v.index()) {
539       case kValue:
540         return std::variant<T, E>(kInPlaceValue, std::get<kValue>(v));
541       case kError:
542         return std::variant<T, E>(kInPlaceError, std::get<kError>(v));
543       default:
544         // Could only happen if valueless_by_exception, which can't be handled
545         // gracefully anyways.
546         std::abort();
547     }
548   }
549 
550   // Helper to convert variant<U, G> -> variant<T, E>
551   template <class U, class G>
convert_variant(std::variant<U,G> && v)552   std::variant<T, E> convert_variant(std::variant<U, G>&& v) {
553     switch (v.index()) {
554       case kValue:
555         return std::variant<T, E>(kInPlaceValue,
556                                   std::forward<U>(std::get<kValue>(v)));
557       case kError:
558         return std::variant<T, E>(kInPlaceError,
559                                   std::forward<G>(std::get<kError>(v)));
560       default:
561         // Could only happen if valueless_by_exception, which can't be handled
562         // gracefully anyways.
563         std::abort();
564     }
565   }
566 
567   // Helper to handle transform correctly for void(Args...) functions, non-void
568   // case.
569   template <class U, class F, std::enable_if_t<!std::is_void_v<U>, bool> = true>
transform_helper(F && f)570   expected<U, E> transform_helper(F&& f) & {
571     return expected<U, E>(std::in_place,
572                           std::invoke(std::forward<F>(f), value()));
573   }
574   template <class U, class F, std::enable_if_t<!std::is_void_v<U>, bool> = true>
transform_helper(F && f)575   expected<U, E> transform_helper(F&& f) && {
576     return expected<U, E>(std::in_place,
577                           std::invoke(std::forward<F>(f), std::move(value())));
578   }
579   template <class U, class F, std::enable_if_t<!std::is_void_v<U>, bool> = true>
transform_helper(F && f)580   expected<U, E> transform_helper(F&& f) const& {
581     return expected<U, E>(std::in_place,
582                           std::invoke(std::forward<F>(f), value()));
583   }
584   template <class U, class F, std::enable_if_t<!std::is_void_v<U>, bool> = true>
transform_helper(F && f)585   expected<U, E> transform_helper(F&& f) const&& {
586     return expected<U, E>(std::in_place,
587                           std::invoke(std::forward<F>(f), std::move(value())));
588   }
589 
590   // Helper to handle transform correctly for void(Args...) functions, void
591   // case.
592   template <class U, class F, std::enable_if_t<std::is_void_v<U>, bool> = true>
transform_helper(F && f)593   expected<U, E> transform_helper(F&& f) & {
594     std::invoke(std::forward<F>(f), value());
595     return expected<U, E>();
596   }
597   template <class U, class F, std::enable_if_t<std::is_void_v<U>, bool> = true>
transform_helper(F && f)598   expected<U, E> transform_helper(F&& f) && {
599     std::invoke(std::forward<F>(f), std::move(value()));
600     return expected<U, E>();
601   }
602   template <class U, class F, std::enable_if_t<std::is_void_v<U>, bool> = true>
transform_helper(F && f)603   expected<U, E> transform_helper(F&& f) const& {
604     std::invoke(std::forward<F>(f), value());
605     return expected<U, E>();
606   }
607   template <class U, class F, std::enable_if_t<std::is_void_v<U>, bool> = true>
transform_helper(F && f)608   expected<U, E> transform_helper(F&& f) const&& {
609     std::invoke(std::forward<F>(f), std::move(value()));
610     return expected<U, E>();
611   }
612 
613   std::variant<T, E> contents_;
614 };
615 
616 template <class T,
617           class E,
618           class U,
619           class G,
620           std::enable_if_t<!std::is_void_v<U>, bool> = true>
621 constexpr bool operator==(const expected<T, E>& lhs,
622                           const expected<U, G>& rhs) {
623   if (lhs.has_value() != rhs.has_value()) {
624     return false;
625   }
626   if (lhs.has_value()) {
627     return lhs.value() == rhs.value();
628   } else {
629     return lhs.error() == rhs.error();
630   }
631 }
632 
633 template <class T, class E, class U>
634 constexpr bool operator==(const expected<T, E>& x, const U& u) {
635   return x.has_value() && static_cast<bool>(*x == u);
636 }
637 
638 template <class T, class E, class G>
639 constexpr bool operator==(const expected<T, E>& x, const unexpected<G> e) {
640   return !x.has_value() && static_cast<bool>(x.error() == e.error());
641 }
642 
643 // Polyfill implementation of std::expected<void, ...>
644 template <class T, class E>
645 class expected<T, E, std::enable_if_t<std::is_void_v<T>>> {
646  public:
647   using value_type = T;
648   using error_type = E;
649   using unexpected_type = unexpected<E>;
650 
651   template <class U>
652   using rebind = expected<U, error_type>;
653 
expected()654   constexpr expected() noexcept : error_contents_(std::nullopt) {}
655   constexpr expected(const expected& rhs) = default;
656   constexpr expected(expected&& rhs) = default;
657   template <
658       class U,
659       class G,
660       // Constraints
661       std::enable_if_t<
662           std::is_void_v<U> && std::is_constructible_v<E, const G&> &&
663               !std::is_constructible_v<unexpected<E>, expected<U, G>&> &&
664               !std::is_constructible_v<unexpected<E>, expected<U, G>> &&
665               !std::is_constructible_v<unexpected<E>, const expected<U, G>&> &&
666               !std::is_constructible_v<unexpected<E>, const expected<U, G>>,
667           bool> = true,
668       // Explicit
669       std::enable_if_t<std::is_convertible_v<const G&, E>, bool> = true>
expected(const expected<U,G> & rhs)670   constexpr /* implicit */ expected(const expected<U, G>& rhs)
671       : error_contents_(rhs.error_contents_.has_value() ? rhs.error_contents_
672                                                         : std::nullopt) {}
673   template <
674       class U,
675       class G,
676       // Constraints
677       std::enable_if_t<
678           std::is_void_v<U> && std::is_constructible_v<E, const G&> &&
679               !std::is_constructible_v<unexpected<E>, expected<U, G>&> &&
680               !std::is_constructible_v<unexpected<E>, expected<U, G>> &&
681               !std::is_constructible_v<unexpected<E>, const expected<U, G>&> &&
682               !std::is_constructible_v<unexpected<E>, const expected<U, G>>,
683           bool> = true,
684       // Explicit
685       std::enable_if_t<!std::is_convertible_v<const G&, E>, bool> = true>
expected(const expected<U,G> & rhs)686   constexpr explicit expected(const expected<U, G>& rhs)
687       : error_contents_(rhs.error_contents_.has_value() ? rhs.error_contents_
688                                                         : std::nullopt) {}
689   template <
690       class U,
691       class G,
692       // Constraints
693       std::enable_if_t<
694           std::is_void_v<U> && std::is_constructible_v<E, G> &&
695               !std::is_constructible_v<unexpected<E>, expected<U, G>&> &&
696               !std::is_constructible_v<unexpected<E>, expected<U, G>> &&
697               !std::is_constructible_v<unexpected<E>, const expected<U, G>&> &&
698               !std::is_constructible_v<unexpected<E>, const expected<U, G>>,
699           bool> = true,
700       // Explicit
701       std::enable_if_t<std::is_convertible_v<G, E>, bool> = true>
expected(expected<U,G> && rhs)702   constexpr /* implicit */ expected(expected<U, G>&& rhs)
703       : error_contents_(rhs.error_contents_.has_value()
704                             ? std::move(rhs.error_contents_)
705                             : std::nullopt) {}
706   template <
707       class U,
708       class G,
709       // Constraints
710       std::enable_if_t<
711           std::is_void_v<U> && std::is_constructible_v<E, G> &&
712               !std::is_constructible_v<unexpected<E>, expected<U, G>&> &&
713               !std::is_constructible_v<unexpected<E>, expected<U, G>> &&
714               !std::is_constructible_v<unexpected<E>, const expected<U, G>&> &&
715               !std::is_constructible_v<unexpected<E>, const expected<U, G>>,
716           bool> = true,
717       // Explicit
718       std::enable_if_t<!std::is_convertible_v<G, E>, bool> = true>
expected(expected<U,G> && rhs)719   constexpr explicit expected(expected<U, G>&& rhs)
720       : error_contents_(rhs.error_contents_.has_value()
721                             ? std::move(rhs.error_contents_)
722                             : std::nullopt) {}
723   template <class G,
724             // Constraints
725             std::enable_if_t<std::is_constructible_v<E, const G&>, bool> = true,
726             // Explicit
727             std::enable_if_t<!std::is_convertible_v<const G&, E>, bool> = true>
expected(const unexpected<G> & e)728   constexpr explicit expected(const unexpected<G>& e)
729       : error_contents_(std::in_place, std::forward<const G&>(e.error())) {}
730   template <class G,
731             // Constraints
732             std::enable_if_t<std::is_constructible_v<E, const G&>, bool> = true,
733             // Explicit
734             std::enable_if_t<std::is_convertible_v<const G&, E>, bool> = true>
expected(const unexpected<G> & e)735   constexpr /* implicit */ expected(const unexpected<G>& e)
736       : error_contents_(std::in_place, std::forward<const G&>(e.error())) {}
737   template <class... Args,
738             std::enable_if_t<std::is_constructible_v<E, Args...>, bool> = true>
expected(unexpect_t,Args &&...args)739   constexpr explicit expected(unexpect_t, Args&&... args)
740       : error_contents_(std::in_place, std::forward<Args>(args)...) {}
741   template <class U,
742             class... Args,
743             std::enable_if_t<
744                 std::is_constructible_v<E, std::initializer_list<U>&, Args...>,
745                 bool> = true>
expected(unexpect_t,std::initializer_list<U> il,Args &&...args)746   constexpr explicit expected(unexpect_t,
747                               std::initializer_list<U> il,
748                               Args&&... args)
749       : error_contents_(std::in_place, il, std::forward<Args>(args)...) {}
750   template <class G,
751             // Constraints
752             std::enable_if_t<std::is_constructible_v<E, G>, bool> = true,
753             // Explicit
754             std::enable_if_t<!std::is_convertible_v<G, E>, bool> = true>
expected(unexpected<G> && e)755   constexpr explicit expected(unexpected<G>&& e)
756       : error_contents_(std::in_place, std::forward<G>(e.error())) {}
757   template <class G,
758             // Constraints
759             std::enable_if_t<std::is_constructible_v<E, G>, bool> = true,
760             // Explicit
761             std::enable_if_t<std::is_convertible_v<G, E>, bool> = true>
expected(unexpected<G> && e)762   constexpr /* implicit */ expected(unexpected<G>&& e)
763       : error_contents_(std::in_place, std::forward<G>(e.error())) {}
764 
765   constexpr expected& operator=(const expected& rhs) {
766     error_contents_ = rhs.error_contents_;
767     return *this;
768   }
noexcept(std::is_nothrow_move_constructible_v<E> && std::is_nothrow_move_assignable_v<E>)769   constexpr expected& operator=(expected&& rhs) noexcept(
770       std::is_nothrow_move_constructible_v<E> &&
771       std::is_nothrow_move_assignable_v<E>) {
772     error_contents_ = std::move(rhs.error_contents_);
773     return *this;
774   }
775   template <class G>
776   constexpr expected& operator=(const unexpected<G>& rhs) {
777     error_contents_ = rhs.error();
778     return *this;
779   }
780   template <class G>
781   constexpr expected& operator=(unexpected<G>&& rhs) {
782     error_contents_ = std::move(rhs.error());
783     return *this;
784   }
785 
swap(expected & rhs)786   constexpr void swap(expected& rhs) {
787     error_contents_.swap(rhs.error_contents_);
788   }
789 
790   constexpr explicit operator bool() const noexcept { return has_value(); }
has_value()791   constexpr bool has_value() const noexcept {
792     return !error_contents_.has_value();
793   }
794 
795   constexpr void operator*() const noexcept {}
value()796   constexpr void value() const& {}
value()797   constexpr void value() && {}
798 
error()799   constexpr E& error() & { return *error_contents_; }
error()800   constexpr E&& error() && { return std::move(*error_contents_); }
error()801   constexpr const E& error() const& { return *error_contents_; }
error()802   constexpr const E&& error() const&& { return std::move(*error_contents_); }
803 
804   template <class G = E>
error_or(G && g)805   constexpr E error_or(G&& g) const& {
806     if (has_value()) {
807       return std::forward<G>(g);
808     } else {
809       return error();
810     }
811   }
812   template <class G = E>
error_or(G && g)813   constexpr E error_or(G&& g) const&& {
814     if (has_value()) {
815       return std::forward<G>(g);
816     } else {
817       return std::move(error());
818     }
819   }
820 
821   template <class F>
and_then(F && f)822   constexpr auto and_then(F&& f) & {
823     using U = remove_cvref_t<std::invoke_result_t<F>>;
824     if (has_value()) {
825       return std::invoke(std::forward<F>(f));
826     } else {
827       return U(unexpect, error());
828     }
829   }
830   template <class F>
and_then(F && f)831   constexpr auto and_then(F&& f) && {
832     using U = remove_cvref_t<std::invoke_result_t<F>>;
833     if (has_value()) {
834       return std::invoke(std::forward<F>(f));
835     } else {
836       return U(unexpect, std::move(error()));
837     }
838   }
839   template <class F>
and_then(F && f)840   constexpr auto and_then(F&& f) const& {
841     using U = remove_cvref_t<std::invoke_result_t<F>>;
842     if (has_value()) {
843       return std::invoke(std::forward<F>(f));
844     } else {
845       return U(unexpect, error());
846     }
847   }
848   template <class F>
and_then(F && f)849   constexpr auto and_then(F&& f) const&& {
850     using U = remove_cvref_t<std::invoke_result_t<F>>;
851     if (has_value()) {
852       return std::invoke(std::forward<F>(f));
853     } else {
854       return U(unexpect, std::move(error()));
855     }
856   }
857 
858   template <class F>
or_else(F && f)859   constexpr auto or_else(F&& f) & {
860     using G = remove_cvref_t<std::invoke_result_t<F, decltype(error())>>;
861     if (has_value()) {
862       return G();
863     } else {
864       return std::invoke(std::forward<F>(f), error());
865     }
866   }
867   template <class F>
or_else(F && f)868   constexpr auto or_else(F&& f) && {
869     using G = remove_cvref_t<std::invoke_result_t<F, decltype(error())>>;
870     if (has_value()) {
871       return G();
872     } else {
873       return std::invoke(std::forward<F>(f), std::move(error()));
874     }
875   }
876   template <class F>
or_else(F && f)877   constexpr auto or_else(F&& f) const& {
878     using G = remove_cvref_t<std::invoke_result_t<F, decltype(error())>>;
879     if (has_value()) {
880       return G();
881     } else {
882       return std::invoke(std::forward<F>(f), error());
883     }
884   }
885   template <class F>
or_else(F && f)886   constexpr auto or_else(F&& f) const&& {
887     using G = remove_cvref_t<std::invoke_result_t<F, decltype(error())>>;
888     if (has_value()) {
889       return G();
890     } else {
891       return std::invoke(std::forward<F>(f), std::move(error()));
892     }
893   }
894 
895   template <class F>
transform(F && f)896   constexpr auto transform(F&& f) & {
897     using U = std::remove_cv_t<std::invoke_result_t<F>>;
898     if (has_value()) {
899       return transform_helper<U>(std::forward<F>(f));
900     } else {
901       return expected<U, E>(unexpect, error());
902     }
903   }
904   template <class F>
transform(F && f)905   constexpr auto transform(F&& f) && {
906     using U = std::remove_cv_t<std::invoke_result_t<F>>;
907     if (has_value()) {
908       return transform_helper<U>(std::forward<F>(f));
909     } else {
910       return expected<U, E>(unexpect, std::move(error()));
911     }
912   }
913   template <class F>
transform(F && f)914   constexpr auto transform(F&& f) const& {
915     using U = std::remove_cv_t<std::invoke_result_t<F>>;
916     if (has_value()) {
917       return transform_helper<U>(std::forward<F>(f));
918     } else {
919       return expected<U, E>(unexpect, error());
920     }
921   }
922   template <class F>
transform(F && f)923   constexpr auto transform(F&& f) const&& {
924     using U = std::remove_cv_t<std::invoke_result_t<F>>;
925     if (has_value()) {
926       return transform_helper<U>(std::forward<F>(f));
927     } else {
928       return expected<U, E>(unexpect, std::move(error()));
929     }
930   }
931 
932   template <class F>
transform_error(F && f)933   constexpr auto transform_error(F&& f) & {
934     using G = std::remove_cv_t<std::invoke_result_t<F, decltype(error())>>;
935     if (has_value()) {
936       return expected<T, G>();
937     } else {
938       return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), error()));
939     }
940   }
941   template <class F>
transform_error(F && f)942   constexpr auto transform_error(F&& f) && {
943     using G = std::remove_cv_t<std::invoke_result_t<F, decltype(error())>>;
944     if (has_value()) {
945       return expected<T, G>();
946     } else {
947       return expected<T, G>(
948           unexpect, std::invoke(std::forward<F>(f), std::move(error())));
949     }
950   }
951   template <class F>
transform_error(F && f)952   constexpr auto transform_error(F&& f) const& {
953     using G = std::remove_cv_t<std::invoke_result_t<F, decltype(error())>>;
954     if (has_value()) {
955       return expected<T, G>();
956     } else {
957       return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), error()));
958     }
959   }
960   template <class F>
transform_error(F && f)961   constexpr auto transform_error(F&& f) const&& {
962     using G = std::remove_cv_t<std::invoke_result_t<F, decltype(error())>>;
963     if (has_value()) {
964       return expected<T, G>();
965     } else {
966       return expected<T, G>(
967           unexpect, std::invoke(std::forward<F>(f), std::move(error())));
968     }
969   }
970 
971  private:
972   // Make all specializations of `expected` friends.
973   template <class U, class G, class>
974   friend class expected;
975 
976   // Helper to handle transform correctly for void(Args...) functions, non-void
977   // case.
978   template <class U, class F, std::enable_if_t<!std::is_void_v<U>, bool> = true>
transform_helper(F && f)979   expected<U, E> transform_helper(F&& f) const {
980     return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f)));
981   }
982 
983   // Helper to handle transform correctly for void(Args...) functions, void
984   // case.
985   template <class U, class F, std::enable_if_t<std::is_void_v<U>, bool> = true>
transform_helper(F && f)986   expected<U, E> transform_helper(F&& f) const {
987     std::invoke(std::forward<F>(f));
988     return expected<U, E>();
989   }
990 
991   std::optional<E> error_contents_;
992 };
993 
994 template <class T,
995           class E,
996           class U,
997           class G,
998           std::enable_if_t<std::is_void_v<U>, bool> = true>
999 constexpr bool operator==(const expected<T, E>& lhs,
1000                           const expected<U, G>& rhs) {
1001   if (lhs.has_value() != rhs.has_value())
1002     return false;
1003   return lhs.has_value() || static_cast<bool>(lhs.error() == rhs.error());
1004 }
1005 
1006 template <class T, class E, class G>
1007 constexpr bool operator==(const expected<T, E>& lhs, const unexpected<G>& rhs) {
1008   return !lhs.has_value() && static_cast<bool>(lhs.error() == rhs.error());
1009 }
1010 
1011 }  // namespace pw::internal
1012