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