WPILibC++ 2025.1.1
Loading...
Searching...
No Matches
expected
Go to the documentation of this file.
1///
2// expected - An implementation of std::expected with extensions
3// Written in 2017 by Sy Brand (tartanllama@gmail.com, @TartanLlama)
4//
5// Documentation available at http://tl.tartanllama.xyz/
6//
7// To the extent possible under law, the author(s) have dedicated all
8// copyright and related and neighboring rights to this software to the
9// public domain worldwide. This software is distributed without any warranty.
10//
11// You should have received a copy of the CC0 Public Domain Dedication
12// along with this software. If not, see
13// <http://creativecommons.org/publicdomain/zero/1.0/>.
14///
15
16#ifndef WPI_EXPECTED_HPP
17#define WPI_EXPECTED_HPP
18
19#define WPI_EXPECTED_VERSION_MAJOR 1
20#define WPI_EXPECTED_VERSION_MINOR 1
21#define WPI_EXPECTED_VERSION_PATCH 0
22
23#include <exception>
24#include <functional>
25#include <type_traits>
26#include <utility>
27
28#if defined(__EXCEPTIONS) || defined(_CPPUNWIND)
29#define WPI_EXPECTED_EXCEPTIONS_ENABLED
30#endif
31
32#if (defined(_MSC_VER) && _MSC_VER == 1900)
33#define WPI_EXPECTED_MSVC2015
34#define WPI_EXPECTED_MSVC2015_CONSTEXPR
35#else
36#define WPI_EXPECTED_MSVC2015_CONSTEXPR constexpr
37#endif
38
39#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \
40 !defined(__clang__))
41#define WPI_EXPECTED_GCC49
42#endif
43
44#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && \
45 !defined(__clang__))
46#define WPI_EXPECTED_GCC54
47#endif
48
49#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && \
50 !defined(__clang__))
51#define WPI_EXPECTED_GCC55
52#endif
53
54#if !defined(WPI_ASSERT)
55//can't have assert in constexpr in C++11 and GCC 4.9 has a compiler bug
56#if (__cplusplus > 201103L) && !defined(WPI_EXPECTED_GCC49)
57#include <cassert>
58#define WPI_ASSERT(x) assert(x)
59#else
60#define WPI_ASSERT(x)
61#endif
62#endif
63
64#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \
65 !defined(__clang__))
66// GCC < 5 doesn't support overloading on const&& for member functions
67
68#define WPI_EXPECTED_NO_CONSTRR
69// GCC < 5 doesn't support some standard C++11 type traits
70#define WPI_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
71 std::has_trivial_copy_constructor<T>
72#define WPI_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
73 std::has_trivial_copy_assign<T>
74
75// This one will be different for GCC 5.7 if it's ever supported
76#define WPI_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \
77 std::is_trivially_destructible<T>
78
79// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks
80// std::vector for non-copyable types
81#elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__))
82#ifndef WPI_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
83#define WPI_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
84namespace wpi {
85namespace detail_expected {
86template <class T>
87struct is_trivially_copy_constructible
88 : std::is_trivially_copy_constructible<T> {};
89#ifdef _GLIBCXX_VECTOR
90template <class T, class A>
91struct is_trivially_copy_constructible<std::vector<T, A>> : std::false_type {};
92#endif
93} // namespace detail_expected
94} // namespace wpi
95#endif
96
97#define WPI_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
98 wpi::detail_expected::is_trivially_copy_constructible<T>
99#define WPI_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
100 std::is_trivially_copy_assignable<T>
101#define WPI_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \
102 std::is_trivially_destructible<T>
103#else
104#define WPI_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
105 std::is_trivially_copy_constructible<T>
106#define WPI_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
107 std::is_trivially_copy_assignable<T>
108#define WPI_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \
109 std::is_trivially_destructible<T>
110#endif
111
112#if __cplusplus > 201103L
113#define WPI_EXPECTED_CXX14
114#endif
115
116#ifdef WPI_EXPECTED_GCC49
117#define WPI_EXPECTED_GCC49_CONSTEXPR
118#else
119#define WPI_EXPECTED_GCC49_CONSTEXPR constexpr
120#endif
121
122#if (__cplusplus == 201103L || defined(WPI_EXPECTED_MSVC2015) || \
123 defined(WPI_EXPECTED_GCC49))
124#define WPI_EXPECTED_11_CONSTEXPR
125#else
126#define WPI_EXPECTED_11_CONSTEXPR constexpr
127#endif
128
129namespace wpi {
130template <class T, class E> class expected;
131
132#ifndef WPI_MONOSTATE_INPLACE_MUTEX
133#define WPI_MONOSTATE_INPLACE_MUTEX
134class monostate {};
135
137 explicit in_place_t() = default;
138};
139static constexpr in_place_t in_place{};
140#endif
141
142template <class E> class unexpected {
143public:
144 static_assert(!std::is_same<E, void>::value, "E must not be void");
145
146 unexpected() = delete;
147 constexpr explicit unexpected(const E &e) : m_val(e) {}
148
149 constexpr explicit unexpected(E &&e) : m_val(std::move(e)) {}
150
151 template <class... Args, typename std::enable_if<std::is_constructible<
152 E, Args &&...>::value>::type * = nullptr>
153 constexpr explicit unexpected(Args &&...args)
154 : m_val(std::forward<Args>(args)...) {}
155 template <
156 class U, class... Args,
157 typename std::enable_if<std::is_constructible<
158 E, std::initializer_list<U> &, Args &&...>::value>::type * = nullptr>
159 constexpr explicit unexpected(std::initializer_list<U> l, Args &&...args)
160 : m_val(l, std::forward<Args>(args)...) {}
161
162 constexpr const E &value() const & { return m_val; }
163 WPI_EXPECTED_11_CONSTEXPR E &value() & { return m_val; }
164 WPI_EXPECTED_11_CONSTEXPR E &&value() && { return std::move(m_val); }
165 constexpr const E &&value() const && { return std::move(m_val); }
166
167private:
168 E m_val;
169};
170
171#ifdef __cpp_deduction_guides
172template <class E> unexpected(E) -> unexpected<E>;
173#endif
174
175template <class E>
176constexpr bool operator==(const unexpected<E> &lhs, const unexpected<E> &rhs) {
177 return lhs.value() == rhs.value();
178}
179template <class E>
180constexpr bool operator!=(const unexpected<E> &lhs, const unexpected<E> &rhs) {
181 return lhs.value() != rhs.value();
182}
183template <class E>
184constexpr bool operator<(const unexpected<E> &lhs, const unexpected<E> &rhs) {
185 return lhs.value() < rhs.value();
186}
187template <class E>
188constexpr bool operator<=(const unexpected<E> &lhs, const unexpected<E> &rhs) {
189 return lhs.value() <= rhs.value();
190}
191template <class E>
192constexpr bool operator>(const unexpected<E> &lhs, const unexpected<E> &rhs) {
193 return lhs.value() > rhs.value();
194}
195template <class E>
196constexpr bool operator>=(const unexpected<E> &lhs, const unexpected<E> &rhs) {
197 return lhs.value() >= rhs.value();
198}
199
200template <class E>
204
206 unexpect_t() = default;
207};
208static constexpr unexpect_t unexpect{};
209
210namespace detail_expected {
211template <typename E>
213#ifdef WPI_EXPECTED_EXCEPTIONS_ENABLED
214 throw std::forward<E>(e);
215#else
216 (void)e;
217#ifdef _MSC_VER
218 __assume(0);
219#else
220 __builtin_unreachable();
221#endif
222#endif
223}
224
225#ifndef WPI_TRAITS_MUTEX
226#define WPI_TRAITS_MUTEX
227// C++14-style aliases for brevity
228template <class T> using remove_const_t = typename std::remove_const<T>::type;
229template <class T>
230using remove_reference_t = typename std::remove_reference<T>::type;
231template <class T> using decay_t = typename std::decay<T>::type;
232template <bool E, class T = void>
233using enable_if_t = typename std::enable_if<E, T>::type;
234template <bool B, class T, class F>
235using conditional_t = typename std::conditional<B, T, F>::type;
236
237// std::conjunction from C++17
238template <class...> struct conjunction : std::true_type {};
239template <class B> struct conjunction<B> : B {};
240template <class B, class... Bs>
241struct conjunction<B, Bs...>
242 : std::conditional<bool(B::value), conjunction<Bs...>, B>::type {};
243
244#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L
245#define WPI_TRAITS_LIBCXX_MEM_FN_WORKAROUND
246#endif
247
248// In C++11 mode, there's an issue in libc++'s std::mem_fn
249// which results in a hard-error when using it in a noexcept expression
250// in some cases. This is a check to workaround the common failing case.
251#ifdef WPI_TRAITS_LIBCXX_MEM_FN_WORKAROUND
252template <class T>
253struct is_pointer_to_non_const_member_func : std::false_type {};
254template <class T, class Ret, class... Args>
255struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...)>
256 : std::true_type {};
257template <class T, class Ret, class... Args>
258struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) &>
259 : std::true_type {};
260template <class T, class Ret, class... Args>
261struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) &&>
262 : std::true_type {};
263template <class T, class Ret, class... Args>
264struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile>
265 : std::true_type {};
266template <class T, class Ret, class... Args>
267struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile &>
268 : std::true_type {};
269template <class T, class Ret, class... Args>
270struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile &&>
271 : std::true_type {};
272
273template <class T> struct is_const_or_const_ref : std::false_type {};
274template <class T> struct is_const_or_const_ref<T const &> : std::true_type {};
275template <class T> struct is_const_or_const_ref<T const> : std::true_type {};
276#endif
277
278// std::invoke from C++17
279// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround
280template <
281 typename Fn, typename... Args,
282#ifdef WPI_TRAITS_LIBCXX_MEM_FN_WORKAROUND
283 typename = enable_if_t<!(is_pointer_to_non_const_member_func<Fn>::value &&
284 is_const_or_const_ref<Args...>::value)>,
285#endif
286 typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>, int = 0>
287constexpr auto invoke(Fn &&f, Args &&...args) noexcept(
288 noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))
289 -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) {
290 return std::mem_fn(f)(std::forward<Args>(args)...);
291}
292
293template <typename Fn, typename... Args,
295constexpr auto invoke(Fn &&f, Args &&...args) noexcept(
296 noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))
297 -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) {
298 return std::forward<Fn>(f)(std::forward<Args>(args)...);
299}
300
301// std::invoke_result from C++17
302template <class F, class, class... Us> struct invoke_result_impl;
303
304template <class F, class... Us>
306 F,
307 decltype(detail_expected::invoke(std::declval<F>(), std::declval<Us>()...), void()),
308 Us...> {
309 using type =
310 decltype(detail_expected::invoke(std::declval<F>(), std::declval<Us>()...));
311};
312
313template <class F, class... Us>
314using invoke_result = invoke_result_impl<F, void, Us...>;
315
316template <class F, class... Us>
317using invoke_result_t = typename invoke_result<F, Us...>::type;
318
319#if defined(_MSC_VER) && _MSC_VER <= 1900
320// TODO make a version which works with MSVC 2015
321template <class T, class U = T> struct is_swappable : std::true_type {};
322
323template <class T, class U = T> struct is_nothrow_swappable : std::true_type {};
324#else
325// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept
326namespace swap_adl_tests {
327// if swap ADL finds this then it would call std::swap otherwise (same
328// signature)
329struct tag {};
330
331template <class T> tag swap(T &, T &);
332template <class T, std::size_t N> tag swap(T (&a)[N], T (&b)[N]);
333
334// helper functions to test if an unqualified swap is possible, and if it
335// becomes std::swap
336template <class, class> std::false_type can_swap(...) noexcept(false);
337template <class T, class U,
338 class = decltype(swap(std::declval<T &>(), std::declval<U &>()))>
339std::true_type can_swap(int) noexcept(noexcept(swap(std::declval<T &>(),
340 std::declval<U &>())));
341
342template <class, class> std::false_type uses_std(...);
343template <class T, class U>
344std::is_same<decltype(swap(std::declval<T &>(), std::declval<U &>())), tag>
346
347template <class T>
349 : std::integral_constant<bool,
350 std::is_nothrow_move_constructible<T>::value &&
351 std::is_nothrow_move_assignable<T>::value> {};
352
353template <class T, std::size_t N>
355
356template <class T, class U>
358 : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};
359} // namespace swap_adl_tests
360
361template <class T, class U = T>
363 : std::integral_constant<
364 bool,
365 decltype(detail_expected::swap_adl_tests::can_swap<T, U>(0))::value &&
366 (!decltype(detail_expected::swap_adl_tests::uses_std<T, U>(0))::value ||
367 (std::is_move_assignable<T>::value &&
368 std::is_move_constructible<T>::value))> {};
369
370template <class T, std::size_t N>
371struct is_swappable<T[N], T[N]>
372 : std::integral_constant<
373 bool,
374 decltype(detail_expected::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&
375 (!decltype(detail_expected::swap_adl_tests::uses_std<T[N], T[N]>(
376 0))::value ||
377 is_swappable<T, T>::value)> {};
378
379template <class T, class U = T>
381 : std::integral_constant<
382 bool,
383 is_swappable<T, U>::value &&
384 ((decltype(detail_expected::swap_adl_tests::uses_std<T, U>(0))::value &&
385 detail_expected::swap_adl_tests::is_std_swap_noexcept<T>::value) ||
386 (!decltype(detail_expected::swap_adl_tests::uses_std<T, U>(0))::value &&
387 detail_expected::swap_adl_tests::is_adl_swap_noexcept<T, U>::value))> {};
388#endif
389#endif
390
391// Trait for checking if a type is a wpi::expected
392template <class T> struct is_expected_impl : std::false_type {};
393template <class T, class E>
394struct is_expected_impl<expected<T, E>> : std::true_type {};
395template <class T> using is_expected = is_expected_impl<decay_t<T>>;
396
397template <class T, class E, class U>
399 std::is_constructible<T, U &&>::value &&
400 !std::is_same<detail_expected::decay_t<U>, in_place_t>::value &&
401 !std::is_same<expected<T, E>, detail_expected::decay_t<U>>::value &&
402 !std::is_same<unexpected<E>, detail_expected::decay_t<U>>::value>;
403
404template <class T, class E, class U, class G, class UR, class GR>
406 std::is_constructible<T, UR>::value &&
407 std::is_constructible<E, GR>::value &&
408 !std::is_constructible<T, expected<U, G> &>::value &&
409 !std::is_constructible<T, expected<U, G> &&>::value &&
410 !std::is_constructible<T, const expected<U, G> &>::value &&
411 !std::is_constructible<T, const expected<U, G> &&>::value &&
412 !std::is_convertible<expected<U, G> &, T>::value &&
413 !std::is_convertible<expected<U, G> &&, T>::value &&
414 !std::is_convertible<const expected<U, G> &, T>::value &&
415 !std::is_convertible<const expected<U, G> &&, T>::value>;
416
417template <class T, class U>
419
420template <class T>
423
424template <class T>
427
428template <class T>
430
431template <class T>
433
434} // namespace detail_expected
435
436namespace detail_expected {
437struct no_init_t {};
438static constexpr no_init_t no_init{};
439
440// Implements the storage of the values, and ensures that the destructor is
441// trivial if it can be.
442//
443// This specialization is for where neither `T` or `E` is trivially
444// destructible, so the destructors must be called on destruction of the
445// `expected`
446template <class T, class E, bool = std::is_trivially_destructible<T>::value,
447 bool = std::is_trivially_destructible<E>::value>
449 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
451
452 template <class... Args,
453 detail_expected::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
454 nullptr>
455 constexpr expected_storage_base(in_place_t, Args &&...args)
456 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
457
458 template <class U, class... Args,
459 detail_expected::enable_if_t<std::is_constructible<
460 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
461 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
462 Args &&...args)
463 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
464 template <class... Args,
465 detail_expected::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
466 nullptr>
467 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
468 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
469
470 template <class U, class... Args,
471 detail_expected::enable_if_t<std::is_constructible<
472 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
474 std::initializer_list<U> il,
475 Args &&...args)
476 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
477
479 if (m_has_val) {
480 m_val.~T();
481 } else {
482 m_unexpect.~unexpected<E>();
483 }
484 }
485 union {
489 };
491};
492
493// This specialization is for when both `T` and `E` are trivially-destructible,
494// so the destructor of the `expected` can be trivial.
495template <class T, class E> struct expected_storage_base<T, E, true, true> {
496 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
497 constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}
498
499 template <class... Args,
500 detail_expected::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
501 nullptr>
502 constexpr expected_storage_base(in_place_t, Args &&...args)
503 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
504
505 template <class U, class... Args,
506 detail_expected::enable_if_t<std::is_constructible<
507 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
508 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
509 Args &&...args)
510 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
511 template <class... Args,
512 detail_expected::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
513 nullptr>
514 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
515 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
516
517 template <class U, class... Args,
518 detail_expected::enable_if_t<std::is_constructible<
519 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
521 std::initializer_list<U> il,
522 Args &&...args)
523 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
524
526 union {
530 };
532};
533
534// T is trivial, E is not.
535template <class T, class E> struct expected_storage_base<T, E, true, false> {
536 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
538 : m_no_init(), m_has_val(false) {}
539
540 template <class... Args,
541 detail_expected::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
542 nullptr>
543 constexpr expected_storage_base(in_place_t, Args &&...args)
544 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
545
546 template <class U, class... Args,
547 detail_expected::enable_if_t<std::is_constructible<
548 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
549 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
550 Args &&...args)
551 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
552 template <class... Args,
553 detail_expected::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
554 nullptr>
555 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
556 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
557
558 template <class U, class... Args,
559 detail_expected::enable_if_t<std::is_constructible<
560 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
562 std::initializer_list<U> il,
563 Args &&...args)
564 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
565
567 if (!m_has_val) {
568 m_unexpect.~unexpected<E>();
569 }
570 }
571
572 union {
576 };
578};
579
580// E is trivial, T is not.
581template <class T, class E> struct expected_storage_base<T, E, false, true> {
582 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
583 constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}
584
585 template <class... Args,
586 detail_expected::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
587 nullptr>
588 constexpr expected_storage_base(in_place_t, Args &&...args)
589 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
590
591 template <class U, class... Args,
592 detail_expected::enable_if_t<std::is_constructible<
593 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
594 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
595 Args &&...args)
596 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
597 template <class... Args,
598 detail_expected::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
599 nullptr>
600 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
601 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
602
603 template <class U, class... Args,
604 detail_expected::enable_if_t<std::is_constructible<
605 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
607 std::initializer_list<U> il,
608 Args &&...args)
609 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
610
612 if (m_has_val) {
613 m_val.~T();
614 }
615 }
616 union {
620 };
622};
623
624// `T` is `void`, `E` is trivially-destructible
626 #if __GNUC__ <= 5
627 //no constexpr for GCC 4/5 bug
628 #else
630 #endif
631 expected_storage_base() : m_has_val(true) {}
632
633 constexpr expected_storage_base(no_init_t) : m_val(), m_has_val(false) {}
634
635 constexpr expected_storage_base(in_place_t) : m_has_val(true) {}
636
637 template <class... Args,
638 detail_expected::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
639 nullptr>
640 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
641 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
642
643 template <class U, class... Args,
644 detail_expected::enable_if_t<std::is_constructible<
645 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
647 std::initializer_list<U> il,
648 Args &&...args)
649 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
650
652 struct dummy {};
653 union {
656 };
658};
659
660// `T` is `void`, `E` is not trivially-destructible
662 constexpr expected_storage_base() : m_dummy(), m_has_val(true) {}
663 constexpr expected_storage_base(no_init_t) : m_dummy(), m_has_val(false) {}
664
665 constexpr expected_storage_base(in_place_t) : m_dummy(), m_has_val(true) {}
666
667 template <class... Args,
668 detail_expected::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
669 nullptr>
670 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
671 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
672
673 template <class U, class... Args,
674 detail_expected::enable_if_t<std::is_constructible<
675 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
677 std::initializer_list<U> il,
678 Args &&...args)
679 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
680
682 if (!m_has_val) {
683 m_unexpect.~unexpected<E>();
684 }
685 }
686
687 union {
690 };
692};
693
694// This base class provides some handy member functions which can be used in
695// further derived classes
696template <class T, class E>
698 using expected_storage_base<T, E>::expected_storage_base;
699
700 template <class... Args> void construct(Args &&...args) noexcept {
701 new (std::addressof(this->m_val)) T(std::forward<Args>(args)...);
702 this->m_has_val = true;
703 }
704
705 template <class Rhs> void construct_with(Rhs &&rhs) noexcept {
706 new (std::addressof(this->m_val)) T(std::forward<Rhs>(rhs).get());
707 this->m_has_val = true;
708 }
709
710 template <class... Args> void construct_error(Args &&...args) noexcept {
711 new (std::addressof(this->m_unexpect))
712 unexpected<E>(std::forward<Args>(args)...);
713 this->m_has_val = false;
714 }
715
716#ifdef WPI_EXPECTED_EXCEPTIONS_ENABLED
717
718 // These assign overloads ensure that the most efficient assignment
719 // implementation is used while maintaining the strong exception guarantee.
720 // The problematic case is where rhs has a value, but *this does not.
721 //
722 // This overload handles the case where we can just copy-construct `T`
723 // directly into place without throwing.
724 template <class U = T,
726 * = nullptr>
727 void assign(const expected_operations_base &rhs) noexcept {
728 if (!this->m_has_val && rhs.m_has_val) {
729 geterr().~unexpected<E>();
730 construct(rhs.get());
731 } else {
732 assign_common(rhs);
733 }
734 }
735
736 // This overload handles the case where we can attempt to create a copy of
737 // `T`, then no-throw move it into place if the copy was successful.
738 template <class U = T,
739 detail_expected::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
740 std::is_nothrow_move_constructible<U>::value>
741 * = nullptr>
742 void assign(const expected_operations_base &rhs) noexcept {
743 if (!this->m_has_val && rhs.m_has_val) {
744 T tmp = rhs.get();
745 geterr().~unexpected<E>();
746 construct(std::move(tmp));
747 } else {
748 assign_common(rhs);
749 }
750 }
751
752 // This overload is the worst-case, where we have to move-construct the
753 // unexpected value into temporary storage, then try to copy the T into place.
754 // If the construction succeeds, then everything is fine, but if it throws,
755 // then we move the old unexpected value back into place before rethrowing the
756 // exception.
757 template <class U = T,
758 detail_expected::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
759 !std::is_nothrow_move_constructible<U>::value>
760 * = nullptr>
761 void assign(const expected_operations_base &rhs) {
762 if (!this->m_has_val && rhs.m_has_val) {
763 auto tmp = std::move(geterr());
764 geterr().~unexpected<E>();
765
766#ifdef WPI_EXPECTED_EXCEPTIONS_ENABLED
767 try {
768 construct(rhs.get());
769 } catch (...) {
770 geterr() = std::move(tmp);
771 throw;
772 }
773#else
774 construct(rhs.get());
775#endif
776 } else {
777 assign_common(rhs);
778 }
779 }
780
781 // These overloads do the same as above, but for rvalues
782 template <class U = T,
783 detail_expected::enable_if_t<std::is_nothrow_move_constructible<U>::value>
784 * = nullptr>
785 void assign(expected_operations_base &&rhs) noexcept {
786 if (!this->m_has_val && rhs.m_has_val) {
787 geterr().~unexpected<E>();
788 construct(std::move(rhs).get());
789 } else {
790 assign_common(std::move(rhs));
791 }
792 }
793
794 template <class U = T,
795 detail_expected::enable_if_t<!std::is_nothrow_move_constructible<U>::value>
796 * = nullptr>
797 void assign(expected_operations_base &&rhs) {
798 if (!this->m_has_val && rhs.m_has_val) {
799 auto tmp = std::move(geterr());
800 geterr().~unexpected<E>();
801#ifdef WPI_EXPECTED_EXCEPTIONS_ENABLED
802 try {
803 construct(std::move(rhs).get());
804 } catch (...) {
805 geterr() = std::move(tmp);
806 throw;
807 }
808#else
809 construct(std::move(rhs).get());
810#endif
811 } else {
812 assign_common(std::move(rhs));
813 }
814 }
815
816#else
817
818 // If exceptions are disabled then we can just copy-construct
819 void assign(const expected_operations_base &rhs) noexcept {
820 if (!this->m_has_val && rhs.m_has_val) {
821 geterr().~unexpected<E>();
822 construct(rhs.get());
823 } else {
824 assign_common(rhs);
825 }
826 }
827
828 void assign(expected_operations_base &&rhs) noexcept {
829 if (!this->m_has_val && rhs.m_has_val) {
830 geterr().~unexpected<E>();
831 construct(std::move(rhs).get());
832 } else {
833 assign_common(std::move(rhs));
834 }
835 }
836
837#endif
838
839 // The common part of move/copy assigning
840 template <class Rhs> void assign_common(Rhs &&rhs) {
841 if (this->m_has_val) {
842 if (rhs.m_has_val) {
843 get() = std::forward<Rhs>(rhs).get();
844 } else {
845 destroy_val();
846 construct_error(std::forward<Rhs>(rhs).geterr());
847 }
848 } else {
849 if (!rhs.m_has_val) {
850 geterr() = std::forward<Rhs>(rhs).geterr();
851 }
852 }
853 }
854
855 bool has_value() const { return this->m_has_val; }
856
857 WPI_EXPECTED_11_CONSTEXPR T &get() & { return this->m_val; }
858 constexpr const T &get() const & { return this->m_val; }
859 WPI_EXPECTED_11_CONSTEXPR T &&get() && { return std::move(this->m_val); }
860#ifndef WPI_EXPECTED_NO_CONSTRR
861 constexpr const T &&get() const && { return std::move(this->m_val); }
862#endif
863
865 return this->m_unexpect;
866 }
867 constexpr const unexpected<E> &geterr() const & { return this->m_unexpect; }
869 return std::move(this->m_unexpect);
870 }
871#ifndef WPI_EXPECTED_NO_CONSTRR
872 constexpr const unexpected<E> &&geterr() const && {
873 return std::move(this->m_unexpect);
874 }
875#endif
876
878};
879
880// This base class provides some handy member functions which can be used in
881// further derived classes
882template <class E>
885
886 template <class... Args> void construct() noexcept { this->m_has_val = true; }
887
888 // This function doesn't use its argument, but needs it so that code in
889 // levels above this can work independently of whether T is void
890 template <class Rhs> void construct_with(Rhs &&) noexcept {
891 this->m_has_val = true;
892 }
893
894 template <class... Args> void construct_error(Args &&...args) noexcept {
895 new (std::addressof(this->m_unexpect))
896 unexpected<E>(std::forward<Args>(args)...);
897 this->m_has_val = false;
898 }
899
900 template <class Rhs> void assign(Rhs &&rhs) noexcept {
901 if (!this->m_has_val) {
902 if (rhs.m_has_val) {
903 geterr().~unexpected<E>();
904 construct();
905 } else {
906 geterr() = std::forward<Rhs>(rhs).geterr();
907 }
908 } else {
909 if (!rhs.m_has_val) {
910 construct_error(std::forward<Rhs>(rhs).geterr());
911 }
912 }
913 }
914
915 bool has_value() const { return this->m_has_val; }
916
920 constexpr const unexpected<E> &geterr() const & { return this->m_unexpect; }
922 return std::move(this->m_unexpect);
923 }
924#ifndef WPI_EXPECTED_NO_CONSTRR
925 constexpr const unexpected<E> &&geterr() const && {
926 return std::move(this->m_unexpect);
927 }
928#endif
929
931 // no-op
932 }
933};
934
935// This class manages conditionally having a trivial copy constructor
936// This specialization is for when T and E are trivially copy constructible
937template <class T, class E,
941 using expected_operations_base<T, E>::expected_operations_base;
942};
943
944// This specialization is for when T or E are not trivially copy constructible
945template <class T, class E>
947 using expected_operations_base<T, E>::expected_operations_base;
948
952 if (rhs.has_value()) {
953 this->construct_with(rhs);
954 } else {
955 this->construct_error(rhs.geterr());
956 }
957 }
958
962};
963
964// This class manages conditionally having a trivial move constructor
965// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
966// doesn't implement an analogue to std::is_trivially_move_constructible. We
967// have to make do with a non-trivial move constructor even if T is trivially
968// move constructible
969#ifndef WPI_EXPECTED_GCC49
970template <class T, class E,
972 &&std::is_trivially_move_constructible<E>::value>
974 using expected_copy_base<T, E>::expected_copy_base;
975};
976#else
977template <class T, class E, bool = false> struct expected_move_base;
978#endif
979template <class T, class E>
980struct expected_move_base<T, E, false> : expected_copy_base<T, E> {
981 using expected_copy_base<T, E>::expected_copy_base;
982
985
987 std::is_nothrow_move_constructible<T>::value)
988 : expected_copy_base<T, E>(no_init) {
989 if (rhs.has_value()) {
990 this->construct_with(std::move(rhs));
991 } else {
992 this->construct_error(std::move(rhs.geterr()));
993 }
994 }
997};
998
999// This class manages conditionally having a trivial copy assignment operator
1000template <class T, class E,
1001 bool = is_void_or<
1009 using expected_move_base<T, E>::expected_move_base;
1010};
1011
1012template <class T, class E>
1027
1028// This class manages conditionally having a trivial move assignment operator
1029// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
1030// doesn't implement an analogue to std::is_trivially_move_assignable. We have
1031// to make do with a non-trivial move assignment operator even if T is trivially
1032// move assignable
1033#ifndef WPI_EXPECTED_GCC49
1034template <class T, class E,
1035 bool =
1037 std::is_trivially_move_constructible<T>,
1038 std::is_trivially_move_assignable<T>>>::
1039 value &&std::is_trivially_destructible<E>::value
1040 &&std::is_trivially_move_constructible<E>::value
1041 &&std::is_trivially_move_assignable<E>::value>
1043 using expected_copy_assign_base<T, E>::expected_copy_assign_base;
1044};
1045#else
1046template <class T, class E, bool = false> struct expected_move_assign_base;
1047#endif
1048
1049template <class T, class E>
1050struct expected_move_assign_base<T, E, false>
1052 using expected_copy_assign_base<T, E>::expected_copy_assign_base;
1053
1056
1058
1061
1064 std::is_nothrow_move_constructible<T>::value
1065 &&std::is_nothrow_move_assignable<T>::value) {
1066 this->assign(std::move(rhs));
1067 return *this;
1068 }
1069};
1070
1071// expected_delete_ctor_base will conditionally delete copy and move
1072// constructors depending on whether T is copy/move constructible
1073template <class T, class E,
1074 bool EnableCopy = (is_copy_constructible_or_void<T>::value &&
1075 std::is_copy_constructible<E>::value),
1076 bool EnableMove = (is_move_constructible_or_void<T>::value &&
1077 std::is_move_constructible<E>::value)>
1087
1088template <class T, class E>
1098
1099template <class T, class E>
1109
1110template <class T, class E>
1120
1121// expected_delete_assign_base will conditionally delete copy and move
1122// constructors depending on whether T and E are copy/move constructible +
1123// assignable
1124template <class T, class E,
1125 bool EnableCopy = (is_copy_constructible_or_void<T>::value &&
1126 std::is_copy_constructible<E>::value &&
1127 is_copy_assignable_or_void<T>::value &&
1128 std::is_copy_assignable<E>::value),
1129 bool EnableMove = (is_move_constructible_or_void<T>::value &&
1130 std::is_move_constructible<E>::value &&
1131 is_move_assignable_or_void<T>::value &&
1132 std::is_move_assignable<E>::value)>
1143
1144template <class T, class E>
1155
1156template <class T, class E>
1167
1168template <class T, class E>
1179
1180// This is needed to be able to construct the expected_default_ctor_base which
1181// follows, while still conditionally deleting the default constructor.
1183 explicit constexpr default_constructor_tag() = default;
1184};
1185
1186// expected_default_ctor_base will ensure that expected has a deleted default
1187// consturctor if T is not default constructible.
1188// This specialization is for when T is default constructible
1189template <class T, class E,
1190 bool Enable =
1191 std::is_default_constructible<T>::value || std::is_void<T>::value>
1193 constexpr expected_default_ctor_base() noexcept = default;
1195 expected_default_ctor_base const &) noexcept = default;
1197 default;
1199 operator=(expected_default_ctor_base const &) noexcept = default;
1201 operator=(expected_default_ctor_base &&) noexcept = default;
1202
1204};
1205
1206// This specialization is for when T is not default constructible
1207template <class T, class E> struct expected_default_ctor_base<T, E, false> {
1208 constexpr expected_default_ctor_base() noexcept = delete;
1210 expected_default_ctor_base const &) noexcept = default;
1212 default;
1214 operator=(expected_default_ctor_base const &) noexcept = default;
1216 operator=(expected_default_ctor_base &&) noexcept = default;
1217
1219};
1220} // namespace detail_expected
1221
1222template <class E> class bad_expected_access : public std::exception {
1223public:
1224 explicit bad_expected_access(E e) : m_val(std::move(e)) {}
1225
1226 virtual const char *what() const noexcept override {
1227 return "Bad expected access";
1228 }
1229
1230 const E &error() const & { return m_val; }
1231 E &error() & { return m_val; }
1232 const E &&error() const && { return std::move(m_val); }
1233 E &&error() && { return std::move(m_val); }
1234
1235private:
1236 E m_val;
1237};
1238
1239/// An `expected<T, E>` object is an object that contains the storage for
1240/// another object and manages the lifetime of this contained object `T`.
1241/// Alternatively it could contain the storage for another unexpected object
1242/// `E`. The contained object may not be initialized after the expected object
1243/// has been initialized, and may not be destroyed before the expected object
1244/// has been destroyed. The initialization state of the contained object is
1245/// tracked by the expected object.
1246template <class T, class E>
1251 static_assert(!std::is_reference<T>::value, "T must not be a reference");
1252 static_assert(!std::is_same<T, std::remove_cv<in_place_t>::type>::value,
1253 "T must not be in_place_t");
1254 static_assert(!std::is_same<T, std::remove_cv<unexpect_t>::type>::value,
1255 "T must not be unexpect_t");
1256 static_assert(
1257 !std::is_same<T, typename std::remove_cv<unexpected<E>>::type>::value,
1258 "T must not be unexpected<E>");
1259 static_assert(!std::is_reference<E>::value, "E must not be a reference");
1260
1261 T *valptr() { return std::addressof(this->m_val); }
1262 const T *valptr() const { return std::addressof(this->m_val); }
1263 unexpected<E> *errptr() { return std::addressof(this->m_unexpect); }
1264 const unexpected<E> *errptr() const {
1265 return std::addressof(this->m_unexpect);
1266 }
1267
1268 template <class U = T,
1270 WPI_EXPECTED_11_CONSTEXPR U &val() {
1271 return this->m_val;
1272 }
1273 WPI_EXPECTED_11_CONSTEXPR unexpected<E> &err() { return this->m_unexpect; }
1274
1275 template <class U = T,
1277 constexpr const U &val() const {
1278 return this->m_val;
1279 }
1280 constexpr const unexpected<E> &err() const { return this->m_unexpect; }
1281
1284
1285public:
1286 typedef T value_type;
1287 typedef E error_type;
1289
1290#if defined(WPI_EXPECTED_CXX14) && !defined(WPI_EXPECTED_GCC49) && \
1291 !defined(WPI_EXPECTED_GCC54) && !defined(WPI_EXPECTED_GCC55)
1292 template <class F> WPI_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & {
1293 return and_then_impl(*this, std::forward<F>(f));
1294 }
1295 template <class F> WPI_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && {
1296 return and_then_impl(std::move(*this), std::forward<F>(f));
1297 }
1298 template <class F> constexpr auto and_then(F &&f) const & {
1299 return and_then_impl(*this, std::forward<F>(f));
1300 }
1301
1302#ifndef WPI_EXPECTED_NO_CONSTRR
1303 template <class F> constexpr auto and_then(F &&f) const && {
1304 return and_then_impl(std::move(*this), std::forward<F>(f));
1305 }
1306#endif
1307
1308#else
1309 template <class F>
1311 and_then(F &&f) & -> decltype(and_then_impl(std::declval<expected &>(),
1312 std::forward<F>(f))) {
1313 return and_then_impl(*this, std::forward<F>(f));
1314 }
1315 template <class F>
1317 and_then(F &&f) && -> decltype(and_then_impl(std::declval<expected &&>(),
1318 std::forward<F>(f))) {
1319 return and_then_impl(std::move(*this), std::forward<F>(f));
1320 }
1321 template <class F>
1322 constexpr auto and_then(F &&f) const & -> decltype(and_then_impl(
1323 std::declval<expected const &>(), std::forward<F>(f))) {
1324 return and_then_impl(*this, std::forward<F>(f));
1325 }
1326
1327#ifndef WPI_EXPECTED_NO_CONSTRR
1328 template <class F>
1329 constexpr auto and_then(F &&f) const && -> decltype(and_then_impl(
1330 std::declval<expected const &&>(), std::forward<F>(f))) {
1331 return and_then_impl(std::move(*this), std::forward<F>(f));
1332 }
1333#endif
1334#endif
1335
1336#if defined(WPI_EXPECTED_CXX14) && !defined(WPI_EXPECTED_GCC49) && \
1337 !defined(WPI_EXPECTED_GCC54) && !defined(WPI_EXPECTED_GCC55)
1338 template <class F> WPI_EXPECTED_11_CONSTEXPR auto map(F &&f) & {
1339 return expected_map_impl(*this, std::forward<F>(f));
1340 }
1341 template <class F> WPI_EXPECTED_11_CONSTEXPR auto map(F &&f) && {
1342 return expected_map_impl(std::move(*this), std::forward<F>(f));
1343 }
1344 template <class F> constexpr auto map(F &&f) const & {
1345 return expected_map_impl(*this, std::forward<F>(f));
1346 }
1347 template <class F> constexpr auto map(F &&f) const && {
1348 return expected_map_impl(std::move(*this), std::forward<F>(f));
1349 }
1350#else
1351 template <class F>
1353 std::declval<expected &>(), std::declval<F &&>()))
1354 map(F &&f) & {
1355 return expected_map_impl(*this, std::forward<F>(f));
1356 }
1357 template <class F>
1358 WPI_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval<expected>(),
1359 std::declval<F &&>()))
1360 map(F &&f) && {
1361 return expected_map_impl(std::move(*this), std::forward<F>(f));
1362 }
1363 template <class F>
1364 constexpr decltype(expected_map_impl(std::declval<const expected &>(),
1365 std::declval<F &&>()))
1366 map(F &&f) const & {
1367 return expected_map_impl(*this, std::forward<F>(f));
1368 }
1369
1370#ifndef WPI_EXPECTED_NO_CONSTRR
1371 template <class F>
1372 constexpr decltype(expected_map_impl(std::declval<const expected &&>(),
1373 std::declval<F &&>()))
1374 map(F &&f) const && {
1375 return expected_map_impl(std::move(*this), std::forward<F>(f));
1376 }
1377#endif
1378#endif
1379
1380#if defined(WPI_EXPECTED_CXX14) && !defined(WPI_EXPECTED_GCC49) && \
1381 !defined(WPI_EXPECTED_GCC54) && !defined(WPI_EXPECTED_GCC55)
1382 template <class F> WPI_EXPECTED_11_CONSTEXPR auto transform(F &&f) & {
1383 return expected_map_impl(*this, std::forward<F>(f));
1384 }
1385 template <class F> WPI_EXPECTED_11_CONSTEXPR auto transform(F &&f) && {
1386 return expected_map_impl(std::move(*this), std::forward<F>(f));
1387 }
1388 template <class F> constexpr auto transform(F &&f) const & {
1389 return expected_map_impl(*this, std::forward<F>(f));
1390 }
1391 template <class F> constexpr auto transform(F &&f) const && {
1392 return expected_map_impl(std::move(*this), std::forward<F>(f));
1393 }
1394#else
1395 template <class F>
1397 std::declval<expected &>(), std::declval<F &&>()))
1398 transform(F &&f) & {
1399 return expected_map_impl(*this, std::forward<F>(f));
1400 }
1401 template <class F>
1402 WPI_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval<expected>(),
1403 std::declval<F &&>()))
1404 transform(F &&f) && {
1405 return expected_map_impl(std::move(*this), std::forward<F>(f));
1406 }
1407 template <class F>
1408 constexpr decltype(expected_map_impl(std::declval<const expected &>(),
1409 std::declval<F &&>()))
1410 transform(F &&f) const & {
1411 return expected_map_impl(*this, std::forward<F>(f));
1412 }
1413
1414#ifndef WPI_EXPECTED_NO_CONSTRR
1415 template <class F>
1416 constexpr decltype(expected_map_impl(std::declval<const expected &&>(),
1417 std::declval<F &&>()))
1418 transform(F &&f) const && {
1419 return expected_map_impl(std::move(*this), std::forward<F>(f));
1420 }
1421#endif
1422#endif
1423
1424#if defined(WPI_EXPECTED_CXX14) && !defined(WPI_EXPECTED_GCC49) && \
1425 !defined(WPI_EXPECTED_GCC54) && !defined(WPI_EXPECTED_GCC55)
1426 template <class F> WPI_EXPECTED_11_CONSTEXPR auto map_error(F &&f) & {
1427 return map_error_impl(*this, std::forward<F>(f));
1428 }
1429 template <class F> WPI_EXPECTED_11_CONSTEXPR auto map_error(F &&f) && {
1430 return map_error_impl(std::move(*this), std::forward<F>(f));
1431 }
1432 template <class F> constexpr auto map_error(F &&f) const & {
1433 return map_error_impl(*this, std::forward<F>(f));
1434 }
1435 template <class F> constexpr auto map_error(F &&f) const && {
1436 return map_error_impl(std::move(*this), std::forward<F>(f));
1437 }
1438#else
1439 template <class F>
1440 WPI_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval<expected &>(),
1441 std::declval<F &&>()))
1442 map_error(F &&f) & {
1443 return map_error_impl(*this, std::forward<F>(f));
1444 }
1445 template <class F>
1446 WPI_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval<expected &&>(),
1447 std::declval<F &&>()))
1448 map_error(F &&f) && {
1449 return map_error_impl(std::move(*this), std::forward<F>(f));
1450 }
1451 template <class F>
1452 constexpr decltype(map_error_impl(std::declval<const expected &>(),
1453 std::declval<F &&>()))
1454 map_error(F &&f) const & {
1455 return map_error_impl(*this, std::forward<F>(f));
1456 }
1457
1458#ifndef WPI_EXPECTED_NO_CONSTRR
1459 template <class F>
1460 constexpr decltype(map_error_impl(std::declval<const expected &&>(),
1461 std::declval<F &&>()))
1462 map_error(F &&f) const && {
1463 return map_error_impl(std::move(*this), std::forward<F>(f));
1464 }
1465#endif
1466#endif
1467#if defined(WPI_EXPECTED_CXX14) && !defined(WPI_EXPECTED_GCC49) && \
1468 !defined(WPI_EXPECTED_GCC54) && !defined(WPI_EXPECTED_GCC55)
1469 template <class F> WPI_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) & {
1470 return map_error_impl(*this, std::forward<F>(f));
1471 }
1472 template <class F> WPI_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) && {
1473 return map_error_impl(std::move(*this), std::forward<F>(f));
1474 }
1475 template <class F> constexpr auto transform_error(F &&f) const & {
1476 return map_error_impl(*this, std::forward<F>(f));
1477 }
1478 template <class F> constexpr auto transform_error(F &&f) const && {
1479 return map_error_impl(std::move(*this), std::forward<F>(f));
1480 }
1481#else
1482 template <class F>
1483 WPI_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval<expected &>(),
1484 std::declval<F &&>()))
1486 return map_error_impl(*this, std::forward<F>(f));
1487 }
1488 template <class F>
1489 WPI_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval<expected &&>(),
1490 std::declval<F &&>()))
1492 return map_error_impl(std::move(*this), std::forward<F>(f));
1493 }
1494 template <class F>
1495 constexpr decltype(map_error_impl(std::declval<const expected &>(),
1496 std::declval<F &&>()))
1497 transform_error(F &&f) const & {
1498 return map_error_impl(*this, std::forward<F>(f));
1499 }
1500
1501#ifndef WPI_EXPECTED_NO_CONSTRR
1502 template <class F>
1503 constexpr decltype(map_error_impl(std::declval<const expected &&>(),
1504 std::declval<F &&>()))
1505 transform_error(F &&f) const && {
1506 return map_error_impl(std::move(*this), std::forward<F>(f));
1507 }
1508#endif
1509#endif
1510 template <class F> expected WPI_EXPECTED_11_CONSTEXPR or_else(F &&f) & {
1511 return or_else_impl(*this, std::forward<F>(f));
1512 }
1513
1514 template <class F> expected WPI_EXPECTED_11_CONSTEXPR or_else(F &&f) && {
1515 return or_else_impl(std::move(*this), std::forward<F>(f));
1516 }
1517
1518 template <class F> expected constexpr or_else(F &&f) const & {
1519 return or_else_impl(*this, std::forward<F>(f));
1520 }
1521
1522#ifndef WPI_EXPECTED_NO_CONSTRR
1523 template <class F> expected constexpr or_else(F &&f) const && {
1524 return or_else_impl(std::move(*this), std::forward<F>(f));
1525 }
1526#endif
1527 constexpr expected() = default;
1528 constexpr expected(const expected &rhs) = default;
1529 constexpr expected(expected &&rhs) = default;
1530 expected &operator=(const expected &rhs) = default;
1531 expected &operator=(expected &&rhs) = default;
1532
1533 template <class... Args,
1534 detail_expected::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
1535 nullptr>
1536 constexpr expected(in_place_t, Args &&...args)
1537 : impl_base(in_place, std::forward<Args>(args)...),
1538 ctor_base(detail_expected::default_constructor_tag{}) {}
1539
1540 template <class U, class... Args,
1541 detail_expected::enable_if_t<std::is_constructible<
1542 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
1543 constexpr expected(in_place_t, std::initializer_list<U> il, Args &&...args)
1544 : impl_base(in_place, il, std::forward<Args>(args)...),
1545 ctor_base(detail_expected::default_constructor_tag{}) {}
1546
1547 template <class G = E,
1549 nullptr,
1551 nullptr>
1552 explicit constexpr expected(const unexpected<G> &e)
1553 : impl_base(unexpect, e.value()),
1554 ctor_base(detail_expected::default_constructor_tag{}) {}
1555
1556 template <
1557 class G = E,
1559 nullptr,
1561 constexpr expected(unexpected<G> const &e)
1562 : impl_base(unexpect, e.value()),
1563 ctor_base(detail_expected::default_constructor_tag{}) {}
1564
1565 template <
1566 class G = E,
1569 explicit constexpr expected(unexpected<G> &&e) noexcept(
1570 std::is_nothrow_constructible<E, G &&>::value)
1571 : impl_base(unexpect, std::move(e.value())),
1572 ctor_base(detail_expected::default_constructor_tag{}) {}
1573
1574 template <
1575 class G = E,
1578 constexpr expected(unexpected<G> &&e) noexcept(
1579 std::is_nothrow_constructible<E, G &&>::value)
1580 : impl_base(unexpect, std::move(e.value())),
1581 ctor_base(detail_expected::default_constructor_tag{}) {}
1582
1583 template <class... Args,
1584 detail_expected::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
1585 nullptr>
1586 constexpr explicit expected(unexpect_t, Args &&...args)
1587 : impl_base(unexpect, std::forward<Args>(args)...),
1588 ctor_base(detail_expected::default_constructor_tag{}) {}
1589
1590 template <class U, class... Args,
1591 detail_expected::enable_if_t<std::is_constructible<
1592 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
1593 constexpr explicit expected(unexpect_t, std::initializer_list<U> il,
1594 Args &&...args)
1595 : impl_base(unexpect, il, std::forward<Args>(args)...),
1596 ctor_base(detail_expected::default_constructor_tag{}) {}
1597
1598 template <class U, class G,
1599 detail_expected::enable_if_t<!(std::is_convertible<U const &, T>::value &&
1600 std::is_convertible<G const &, E>::value)> * =
1601 nullptr,
1603 * = nullptr>
1605 : ctor_base(detail_expected::default_constructor_tag{}) {
1606 if (rhs.has_value()) {
1607 this->construct(*rhs);
1608 } else {
1609 this->construct_error(rhs.error());
1610 }
1611 }
1612
1613 template <class U, class G,
1614 detail_expected::enable_if_t<(std::is_convertible<U const &, T>::value &&
1615 std::is_convertible<G const &, E>::value)> * =
1616 nullptr,
1618 * = nullptr>
1620 : ctor_base(detail_expected::default_constructor_tag{}) {
1621 if (rhs.has_value()) {
1622 this->construct(*rhs);
1623 } else {
1624 this->construct_error(rhs.error());
1625 }
1626 }
1627
1628 template <
1629 class U, class G,
1630 detail_expected::enable_if_t<!(std::is_convertible<U &&, T>::value &&
1631 std::is_convertible<G &&, E>::value)> * = nullptr,
1634 : ctor_base(detail_expected::default_constructor_tag{}) {
1635 if (rhs.has_value()) {
1636 this->construct(std::move(*rhs));
1637 } else {
1638 this->construct_error(std::move(rhs.error()));
1639 }
1640 }
1641
1642 template <
1643 class U, class G,
1644 detail_expected::enable_if_t<(std::is_convertible<U &&, T>::value &&
1645 std::is_convertible<G &&, E>::value)> * = nullptr,
1648 : ctor_base(detail_expected::default_constructor_tag{}) {
1649 if (rhs.has_value()) {
1650 this->construct(std::move(*rhs));
1651 } else {
1652 this->construct_error(std::move(rhs.error()));
1653 }
1654 }
1655
1656 template <
1657 class U = T,
1661 : expected(in_place, std::forward<U>(v)) {}
1662
1663 template <
1664 class U = T,
1669
1670 template <
1671 class U = T, class G = T,
1673 nullptr,
1676 (!std::is_same<expected<T, E>, detail_expected::decay_t<U>>::value &&
1678 std::is_same<T, detail_expected::decay_t<U>>>::value &&
1679 std::is_constructible<T, U>::value &&
1680 std::is_assignable<G &, U>::value &&
1681 std::is_nothrow_move_constructible<E>::value)> * = nullptr>
1683 if (has_value()) {
1684 val() = std::forward<U>(v);
1685 } else {
1686 err().~unexpected<E>();
1687 ::new (valptr()) T(std::forward<U>(v));
1688 this->m_has_val = true;
1689 }
1690
1691 return *this;
1692 }
1693
1694 template <
1695 class U = T, class G = T,
1697 nullptr,
1700 (!std::is_same<expected<T, E>, detail_expected::decay_t<U>>::value &&
1702 std::is_same<T, detail_expected::decay_t<U>>>::value &&
1703 std::is_constructible<T, U>::value &&
1704 std::is_assignable<G &, U>::value &&
1705 std::is_nothrow_move_constructible<E>::value)> * = nullptr>
1706 expected &operator=(U &&v) {
1707 if (has_value()) {
1708 val() = std::forward<U>(v);
1709 } else {
1710 auto tmp = std::move(err());
1711 err().~unexpected<E>();
1712
1713#ifdef WPI_EXPECTED_EXCEPTIONS_ENABLED
1714 try {
1715 ::new (valptr()) T(std::forward<U>(v));
1716 this->m_has_val = true;
1717 } catch (...) {
1718 err() = std::move(tmp);
1719 throw;
1720 }
1721#else
1722 ::new (valptr()) T(std::forward<U>(v));
1723 this->m_has_val = true;
1724#endif
1725 }
1726
1727 return *this;
1728 }
1729
1730 template <class G = E,
1732 std::is_assignable<G &, G>::value> * = nullptr>
1734 if (!has_value()) {
1735 err() = rhs;
1736 } else {
1737 this->destroy_val();
1738 ::new (errptr()) unexpected<E>(rhs);
1739 this->m_has_val = false;
1740 }
1741
1742 return *this;
1743 }
1744
1745 template <class G = E,
1747 std::is_move_assignable<G>::value> * = nullptr>
1749 if (!has_value()) {
1750 err() = std::move(rhs);
1751 } else {
1752 this->destroy_val();
1753 ::new (errptr()) unexpected<E>(std::move(rhs));
1754 this->m_has_val = false;
1755 }
1756
1757 return *this;
1758 }
1759
1760 template <class... Args, detail_expected::enable_if_t<std::is_nothrow_constructible<
1761 T, Args &&...>::value> * = nullptr>
1762 void emplace(Args &&...args) {
1763 if (has_value()) {
1764 val().~T();
1765 } else {
1766 err().~unexpected<E>();
1767 this->m_has_val = true;
1768 }
1769 ::new (valptr()) T(std::forward<Args>(args)...);
1770 }
1771
1772 template <class... Args, detail_expected::enable_if_t<!std::is_nothrow_constructible<
1773 T, Args &&...>::value> * = nullptr>
1774 void emplace(Args &&...args) {
1775 if (has_value()) {
1776 val().~T();
1777 ::new (valptr()) T(std::forward<Args>(args)...);
1778 } else {
1779 auto tmp = std::move(err());
1780 err().~unexpected<E>();
1781
1782#ifdef WPI_EXPECTED_EXCEPTIONS_ENABLED
1783 try {
1784 ::new (valptr()) T(std::forward<Args>(args)...);
1785 this->m_has_val = true;
1786 } catch (...) {
1787 err() = std::move(tmp);
1788 throw;
1789 }
1790#else
1791 ::new (valptr()) T(std::forward<Args>(args)...);
1792 this->m_has_val = true;
1793#endif
1794 }
1795 }
1796
1797 template <class U, class... Args,
1798 detail_expected::enable_if_t<std::is_nothrow_constructible<
1799 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
1800 void emplace(std::initializer_list<U> il, Args &&...args) {
1801 if (has_value()) {
1802 T t(il, std::forward<Args>(args)...);
1803 val() = std::move(t);
1804 } else {
1805 err().~unexpected<E>();
1806 ::new (valptr()) T(il, std::forward<Args>(args)...);
1807 this->m_has_val = true;
1808 }
1809 }
1810
1811 template <class U, class... Args,
1812 detail_expected::enable_if_t<!std::is_nothrow_constructible<
1813 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
1814 void emplace(std::initializer_list<U> il, Args &&...args) {
1815 if (has_value()) {
1816 T t(il, std::forward<Args>(args)...);
1817 val() = std::move(t);
1818 } else {
1819 auto tmp = std::move(err());
1820 err().~unexpected<E>();
1821
1822#ifdef WPI_EXPECTED_EXCEPTIONS_ENABLED
1823 try {
1824 ::new (valptr()) T(il, std::forward<Args>(args)...);
1825 this->m_has_val = true;
1826 } catch (...) {
1827 err() = std::move(tmp);
1828 throw;
1829 }
1830#else
1831 ::new (valptr()) T(il, std::forward<Args>(args)...);
1832 this->m_has_val = true;
1833#endif
1834 }
1835 }
1836
1837private:
1838 using t_is_void = std::true_type;
1839 using t_is_not_void = std::false_type;
1840 using t_is_nothrow_move_constructible = std::true_type;
1841 using move_constructing_t_can_throw = std::false_type;
1842 using e_is_nothrow_move_constructible = std::true_type;
1843 using move_constructing_e_can_throw = std::false_type;
1844
1845 void swap_where_both_have_value(expected & /*rhs*/, t_is_void) noexcept {
1846 // swapping void is a no-op
1847 }
1848
1849 void swap_where_both_have_value(expected &rhs, t_is_not_void) {
1850 using std::swap;
1851 swap(val(), rhs.val());
1852 }
1853
1854 void swap_where_only_one_has_value(expected &rhs, t_is_void) noexcept(
1855 std::is_nothrow_move_constructible<E>::value) {
1856 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1857 rhs.err().~unexpected_type();
1858 std::swap(this->m_has_val, rhs.m_has_val);
1859 }
1860
1861 void swap_where_only_one_has_value(expected &rhs, t_is_not_void) {
1862 swap_where_only_one_has_value_and_t_is_not_void(
1863 rhs, typename std::is_nothrow_move_constructible<T>::type{},
1864 typename std::is_nothrow_move_constructible<E>::type{});
1865 }
1866
1867 void swap_where_only_one_has_value_and_t_is_not_void(
1868 expected &rhs, t_is_nothrow_move_constructible,
1869 e_is_nothrow_move_constructible) noexcept {
1870 auto temp = std::move(val());
1871 val().~T();
1872 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1873 rhs.err().~unexpected_type();
1874 ::new (rhs.valptr()) T(std::move(temp));
1875 std::swap(this->m_has_val, rhs.m_has_val);
1876 }
1877
1878 void swap_where_only_one_has_value_and_t_is_not_void(
1879 expected &rhs, t_is_nothrow_move_constructible,
1880 move_constructing_e_can_throw) {
1881 auto temp = std::move(val());
1882 val().~T();
1883#ifdef WPI_EXPECTED_EXCEPTIONS_ENABLED
1884 try {
1885 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1886 rhs.err().~unexpected_type();
1887 ::new (rhs.valptr()) T(std::move(temp));
1888 std::swap(this->m_has_val, rhs.m_has_val);
1889 } catch (...) {
1890 val() = std::move(temp);
1891 throw;
1892 }
1893#else
1894 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1895 rhs.err().~unexpected_type();
1896 ::new (rhs.valptr()) T(std::move(temp));
1897 std::swap(this->m_has_val, rhs.m_has_val);
1898#endif
1899 }
1900
1901 void swap_where_only_one_has_value_and_t_is_not_void(
1902 expected &rhs, move_constructing_t_can_throw,
1903 e_is_nothrow_move_constructible) {
1904 auto temp = std::move(rhs.err());
1905 rhs.err().~unexpected_type();
1906#ifdef WPI_EXPECTED_EXCEPTIONS_ENABLED
1907 try {
1908 ::new (rhs.valptr()) T(std::move(val()));
1909 val().~T();
1910 ::new (errptr()) unexpected_type(std::move(temp));
1911 std::swap(this->m_has_val, rhs.m_has_val);
1912 } catch (...) {
1913 rhs.err() = std::move(temp);
1914 throw;
1915 }
1916#else
1917 ::new (rhs.valptr()) T(std::move(val()));
1918 val().~T();
1919 ::new (errptr()) unexpected_type(std::move(temp));
1920 std::swap(this->m_has_val, rhs.m_has_val);
1921#endif
1922 }
1923
1924public:
1925 template <class OT = T, class OE = E>
1926 detail_expected::enable_if_t<detail_expected::is_swappable<OT>::value &&
1927 detail_expected::is_swappable<OE>::value &&
1928 (std::is_nothrow_move_constructible<OT>::value ||
1929 std::is_nothrow_move_constructible<OE>::value)>
1930 swap(expected &rhs) noexcept(
1931 std::is_nothrow_move_constructible<T>::value
1933 &&std::is_nothrow_move_constructible<E>::value
1935 if (has_value() && rhs.has_value()) {
1936 swap_where_both_have_value(rhs, typename std::is_void<T>::type{});
1937 } else if (!has_value() && rhs.has_value()) {
1938 rhs.swap(*this);
1939 } else if (has_value()) {
1940 swap_where_only_one_has_value(rhs, typename std::is_void<T>::type{});
1941 } else {
1942 using std::swap;
1943 swap(err(), rhs.err());
1944 }
1945 }
1946
1947 constexpr const T *operator->() const {
1948 WPI_ASSERT(has_value());
1949 return valptr();
1950 }
1952 WPI_ASSERT(has_value());
1953 return valptr();
1954 }
1955
1956 template <class U = T,
1958 constexpr const U &operator*() const & {
1959 WPI_ASSERT(has_value());
1960 return val();
1961 }
1962 template <class U = T,
1965 WPI_ASSERT(has_value());
1966 return val();
1967 }
1968 template <class U = T,
1970 constexpr const U &&operator*() const && {
1971 WPI_ASSERT(has_value());
1972 return std::move(val());
1973 }
1974 template <class U = T,
1977 WPI_ASSERT(has_value());
1978 return std::move(val());
1979 }
1980
1981 constexpr bool has_value() const noexcept { return this->m_has_val; }
1982 constexpr explicit operator bool() const noexcept { return this->m_has_val; }
1983
1984 template <class U = T,
1987 if (!has_value())
1988 detail_expected::throw_exception(bad_expected_access<E>(err().value()));
1989 return val();
1990 }
1991 template <class U = T,
1994 if (!has_value())
1995 detail_expected::throw_exception(bad_expected_access<E>(err().value()));
1996 return val();
1997 }
1998 template <class U = T,
2000 WPI_EXPECTED_11_CONSTEXPR const U &&value() const && {
2001 if (!has_value())
2002 detail_expected::throw_exception(bad_expected_access<E>(std::move(err()).value()));
2003 return std::move(val());
2004 }
2005 template <class U = T,
2008 if (!has_value())
2009 detail_expected::throw_exception(bad_expected_access<E>(std::move(err()).value()));
2010 return std::move(val());
2011 }
2012
2013 constexpr const E &error() const & {
2014 WPI_ASSERT(!has_value());
2015 return err().value();
2016 }
2018 WPI_ASSERT(!has_value());
2019 return err().value();
2020 }
2021 constexpr const E &&error() const && {
2022 WPI_ASSERT(!has_value());
2023 return std::move(err().value());
2024 }
2026 WPI_ASSERT(!has_value());
2027 return std::move(err().value());
2028 }
2029
2030 template <class U> constexpr T value_or(U &&v) const & {
2031 static_assert(std::is_copy_constructible<T>::value &&
2032 std::is_convertible<U &&, T>::value,
2033 "T must be copy-constructible and convertible to from U&&");
2034 return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));
2035 }
2036 template <class U> WPI_EXPECTED_11_CONSTEXPR T value_or(U &&v) && {
2037 static_assert(std::is_move_constructible<T>::value &&
2038 std::is_convertible<U &&, T>::value,
2039 "T must be move-constructible and convertible to from U&&");
2040 return bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(v));
2041 }
2042};
2043
2044namespace detail_expected {
2045template <class Exp> using exp_t = typename detail_expected::decay_t<Exp>::value_type;
2046template <class Exp> using err_t = typename detail_expected::decay_t<Exp>::error_type;
2047template <class Exp, class Ret> using ret_t = expected<Ret, err_t<Exp>>;
2048
2049#ifdef WPI_EXPECTED_CXX14
2050template <class Exp, class F,
2052 class Ret = decltype(detail_expected::invoke(std::declval<F>(),
2053 *std::declval<Exp>()))>
2054constexpr auto and_then_impl(Exp &&exp, F &&f) {
2055 static_assert(detail_expected::is_expected<Ret>::value, "F must return an expected");
2056
2057 return exp.has_value()
2058 ? detail_expected::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
2059 : Ret(unexpect, std::forward<Exp>(exp).error());
2060}
2061
2062template <class Exp, class F,
2064 class Ret = decltype(detail_expected::invoke(std::declval<F>()))>
2065constexpr auto and_then_impl(Exp &&exp, F &&f) {
2066 static_assert(detail_expected::is_expected<Ret>::value, "F must return an expected");
2067
2068 return exp.has_value() ? detail_expected::invoke(std::forward<F>(f))
2069 : Ret(unexpect, std::forward<Exp>(exp).error());
2070}
2071#else
2072template <class> struct TC;
2073template <class Exp, class F,
2074 class Ret = decltype(detail_expected::invoke(std::declval<F>(),
2075 *std::declval<Exp>())),
2076 detail_expected::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr>
2077auto and_then_impl(Exp &&exp, F &&f) -> Ret {
2078 static_assert(detail_expected::is_expected<Ret>::value, "F must return an expected");
2079
2080 return exp.has_value()
2081 ? detail_expected::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
2082 : Ret(unexpect, std::forward<Exp>(exp).error());
2083}
2084
2085template <class Exp, class F,
2086 class Ret = decltype(detail_expected::invoke(std::declval<F>())),
2087 detail_expected::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr>
2088constexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret {
2089 static_assert(detail_expected::is_expected<Ret>::value, "F must return an expected");
2090
2091 return exp.has_value() ? detail_expected::invoke(std::forward<F>(f))
2092 : Ret(unexpect, std::forward<Exp>(exp).error());
2093}
2094#endif
2095
2096#ifdef WPI_EXPECTED_CXX14
2097template <class Exp, class F,
2099 class Ret = decltype(detail_expected::invoke(std::declval<F>(),
2100 *std::declval<Exp>())),
2101 detail_expected::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2102constexpr auto expected_map_impl(Exp &&exp, F &&f) {
2103 using result = ret_t<Exp, detail_expected::decay_t<Ret>>;
2104 return exp.has_value() ? result(detail_expected::invoke(std::forward<F>(f),
2105 *std::forward<Exp>(exp)))
2106 : result(unexpect, std::forward<Exp>(exp).error());
2107}
2108
2109template <class Exp, class F,
2110 detail_expected::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2111 class Ret = decltype(detail_expected::invoke(std::declval<F>(),
2112 *std::declval<Exp>())),
2113 detail_expected::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2114auto expected_map_impl(Exp &&exp, F &&f) {
2115 using result = expected<void, err_t<Exp>>;
2116 if (exp.has_value()) {
2117 detail_expected::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
2118 return result();
2119 }
2120
2121 return result(unexpect, std::forward<Exp>(exp).error());
2122}
2123
2124template <class Exp, class F,
2125 detail_expected::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2126 class Ret = decltype(detail_expected::invoke(std::declval<F>())),
2127 detail_expected::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2128constexpr auto expected_map_impl(Exp &&exp, F &&f) {
2129 using result = ret_t<Exp, detail_expected::decay_t<Ret>>;
2130 return exp.has_value() ? result(detail_expected::invoke(std::forward<F>(f)))
2131 : result(unexpect, std::forward<Exp>(exp).error());
2132}
2133
2134template <class Exp, class F,
2135 detail_expected::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2136 class Ret = decltype(detail_expected::invoke(std::declval<F>())),
2137 detail_expected::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2138auto expected_map_impl(Exp &&exp, F &&f) {
2139 using result = expected<void, err_t<Exp>>;
2140 if (exp.has_value()) {
2141 detail_expected::invoke(std::forward<F>(f));
2142 return result();
2143 }
2144
2145 return result(unexpect, std::forward<Exp>(exp).error());
2146}
2147#else
2148template <class Exp, class F,
2149 detail_expected::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2150 class Ret = decltype(detail_expected::invoke(std::declval<F>(),
2151 *std::declval<Exp>())),
2152 detail_expected::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2153
2154constexpr auto expected_map_impl(Exp &&exp, F &&f)
2157
2158 return exp.has_value() ? result(detail_expected::invoke(std::forward<F>(f),
2159 *std::forward<Exp>(exp)))
2160 : result(unexpect, std::forward<Exp>(exp).error());
2161}
2162
2163template <class Exp, class F,
2165 class Ret = decltype(detail_expected::invoke(std::declval<F>(),
2166 *std::declval<Exp>())),
2167 detail_expected::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2168
2170 if (exp.has_value()) {
2171 detail_expected::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
2172 return {};
2173 }
2174
2175 return unexpected<err_t<Exp>>(std::forward<Exp>(exp).error());
2176}
2177
2178template <class Exp, class F,
2180 class Ret = decltype(detail_expected::invoke(std::declval<F>())),
2181 detail_expected::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2182
2183constexpr auto expected_map_impl(Exp &&exp, F &&f)
2184 -> ret_t<Exp, detail_expected::decay_t<Ret>> {
2185 using result = ret_t<Exp, detail_expected::decay_t<Ret>>;
2186
2187 return exp.has_value() ? result(detail_expected::invoke(std::forward<F>(f)))
2188 : result(unexpect, std::forward<Exp>(exp).error());
2189}
2190
2191template <class Exp, class F,
2192 detail_expected::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2193 class Ret = decltype(detail_expected::invoke(std::declval<F>())),
2194 detail_expected::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2195
2196auto expected_map_impl(Exp &&exp, F &&f) -> expected<void, err_t<Exp>> {
2197 if (exp.has_value()) {
2198 detail_expected::invoke(std::forward<F>(f));
2199 return {};
2200 }
2201
2202 return unexpected<err_t<Exp>>(std::forward<Exp>(exp).error());
2203}
2204#endif
2205
2206#if defined(WPI_EXPECTED_CXX14) && !defined(WPI_EXPECTED_GCC49) && \
2207 !defined(WPI_EXPECTED_GCC54) && !defined(WPI_EXPECTED_GCC55)
2208template <class Exp, class F,
2209 detail_expected::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2210 class Ret = decltype(detail_expected::invoke(std::declval<F>(),
2211 std::declval<Exp>().error())),
2212 detail_expected::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2213constexpr auto map_error_impl(Exp &&exp, F &&f) {
2214 using result = expected<exp_t<Exp>, detail_expected::decay_t<Ret>>;
2215 return exp.has_value()
2216 ? result(*std::forward<Exp>(exp))
2217 : result(unexpect, detail_expected::invoke(std::forward<F>(f),
2218 std::forward<Exp>(exp).error()));
2219}
2220template <class Exp, class F,
2221 detail_expected::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2222 class Ret = decltype(detail_expected::invoke(std::declval<F>(),
2223 std::declval<Exp>().error())),
2224 detail_expected::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2225auto map_error_impl(Exp &&exp, F &&f) {
2226 using result = expected<exp_t<Exp>, monostate>;
2227 if (exp.has_value()) {
2228 return result(*std::forward<Exp>(exp));
2229 }
2230
2231 detail_expected::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2232 return result(unexpect, monostate{});
2233}
2234template <class Exp, class F,
2235 detail_expected::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2236 class Ret = decltype(detail_expected::invoke(std::declval<F>(),
2237 std::declval<Exp>().error())),
2238 detail_expected::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2239constexpr auto map_error_impl(Exp &&exp, F &&f) {
2240 using result = expected<exp_t<Exp>, detail_expected::decay_t<Ret>>;
2241 return exp.has_value()
2242 ? result()
2243 : result(unexpect, detail_expected::invoke(std::forward<F>(f),
2244 std::forward<Exp>(exp).error()));
2245}
2246template <class Exp, class F,
2247 detail_expected::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2248 class Ret = decltype(detail_expected::invoke(std::declval<F>(),
2249 std::declval<Exp>().error())),
2250 detail_expected::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2251auto map_error_impl(Exp &&exp, F &&f) {
2252 using result = expected<exp_t<Exp>, monostate>;
2253 if (exp.has_value()) {
2254 return result();
2255 }
2256
2257 detail_expected::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2258 return result(unexpect, monostate{});
2259}
2260#else
2261template <class Exp, class F,
2262 detail_expected::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2263 class Ret = decltype(detail_expected::invoke(std::declval<F>(),
2264 std::declval<Exp>().error())),
2265 detail_expected::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2266constexpr auto map_error_impl(Exp &&exp, F &&f)
2269
2270 return exp.has_value()
2271 ? result(*std::forward<Exp>(exp))
2272 : result(unexpect, detail_expected::invoke(std::forward<F>(f),
2273 std::forward<Exp>(exp).error()));
2274}
2275
2276template <class Exp, class F,
2278 class Ret = decltype(detail_expected::invoke(std::declval<F>(),
2279 std::declval<Exp>().error())),
2280 detail_expected::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2282 using result = expected<exp_t<Exp>, monostate>;
2283 if (exp.has_value()) {
2284 return result(*std::forward<Exp>(exp));
2285 }
2286
2287 detail_expected::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2288 return result(unexpect, monostate{});
2289}
2290
2291template <class Exp, class F,
2293 class Ret = decltype(detail_expected::invoke(std::declval<F>(),
2294 std::declval<Exp>().error())),
2295 detail_expected::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2296constexpr auto map_error_impl(Exp &&exp, F &&f)
2299
2300 return exp.has_value()
2301 ? result()
2302 : result(unexpect, detail_expected::invoke(std::forward<F>(f),
2303 std::forward<Exp>(exp).error()));
2304}
2305
2306template <class Exp, class F,
2307 detail_expected::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2308 class Ret = decltype(detail_expected::invoke(std::declval<F>(),
2309 std::declval<Exp>().error())),
2310 detail_expected::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2311auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate> {
2312 using result = expected<exp_t<Exp>, monostate>;
2313 if (exp.has_value()) {
2314 return result();
2315 }
2316
2317 detail_expected::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2318 return result(unexpect, monostate{});
2319}
2320#endif
2321
2322#ifdef WPI_EXPECTED_CXX14
2323template <class Exp, class F,
2324 class Ret = decltype(detail_expected::invoke(std::declval<F>(),
2325 std::declval<Exp>().error())),
2326 detail_expected::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2327constexpr auto or_else_impl(Exp &&exp, F &&f) {
2328 static_assert(detail_expected::is_expected<Ret>::value, "F must return an expected");
2329 return exp.has_value() ? std::forward<Exp>(exp)
2330 : detail_expected::invoke(std::forward<F>(f),
2331 std::forward<Exp>(exp).error());
2332}
2333
2334template <class Exp, class F,
2335 class Ret = decltype(detail_expected::invoke(std::declval<F>(),
2336 std::declval<Exp>().error())),
2337 detail_expected::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2338detail_expected::decay_t<Exp> or_else_impl(Exp &&exp, F &&f) {
2339 return exp.has_value() ? std::forward<Exp>(exp)
2340 : (detail_expected::invoke(std::forward<F>(f),
2341 std::forward<Exp>(exp).error()),
2342 std::forward<Exp>(exp));
2343}
2344#else
2345template <class Exp, class F,
2346 class Ret = decltype(detail_expected::invoke(std::declval<F>(),
2347 std::declval<Exp>().error())),
2348 detail_expected::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2349auto or_else_impl(Exp &&exp, F &&f) -> Ret {
2350 static_assert(detail_expected::is_expected<Ret>::value, "F must return an expected");
2351 return exp.has_value() ? std::forward<Exp>(exp)
2352 : detail_expected::invoke(std::forward<F>(f),
2353 std::forward<Exp>(exp).error());
2354}
2355
2356template <class Exp, class F,
2357 class Ret = decltype(detail_expected::invoke(std::declval<F>(),
2358 std::declval<Exp>().error())),
2359 detail_expected::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2361 return exp.has_value() ? std::forward<Exp>(exp)
2362 : (detail_expected::invoke(std::forward<F>(f),
2363 std::forward<Exp>(exp).error()),
2364 std::forward<Exp>(exp));
2365}
2366#endif
2367} // namespace detail_expected
2368
2369template <class T, class E, class U, class F>
2370constexpr bool operator==(const expected<T, E> &lhs,
2371 const expected<U, F> &rhs) {
2372 return (lhs.has_value() != rhs.has_value())
2373 ? false
2374 : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs);
2375}
2376template <class T, class E, class U, class F>
2377constexpr bool operator!=(const expected<T, E> &lhs,
2378 const expected<U, F> &rhs) {
2379 return (lhs.has_value() != rhs.has_value())
2380 ? true
2381 : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs);
2382}
2383template <class E, class F>
2384constexpr bool operator==(const expected<void, E> &lhs,
2385 const expected<void, F> &rhs) {
2386 return (lhs.has_value() != rhs.has_value())
2387 ? false
2388 : (!lhs.has_value() ? lhs.error() == rhs.error() : true);
2389}
2390template <class E, class F>
2391constexpr bool operator!=(const expected<void, E> &lhs,
2392 const expected<void, F> &rhs) {
2393 return (lhs.has_value() != rhs.has_value())
2394 ? true
2395 : (!lhs.has_value() ? lhs.error() == rhs.error() : false);
2396}
2397
2398template <class T, class E, class U>
2399constexpr bool operator==(const expected<T, E> &x, const U &v) {
2400 return x.has_value() ? *x == v : false;
2401}
2402template <class T, class E, class U>
2403constexpr bool operator==(const U &v, const expected<T, E> &x) {
2404 return x.has_value() ? *x == v : false;
2405}
2406template <class T, class E, class U>
2407constexpr bool operator!=(const expected<T, E> &x, const U &v) {
2408 return x.has_value() ? *x != v : true;
2409}
2410template <class T, class E, class U>
2411constexpr bool operator!=(const U &v, const expected<T, E> &x) {
2412 return x.has_value() ? *x != v : true;
2413}
2414
2415template <class T, class E>
2416constexpr bool operator==(const expected<T, E> &x, const unexpected<E> &e) {
2417 return x.has_value() ? false : x.error() == e.value();
2418}
2419template <class T, class E>
2420constexpr bool operator==(const unexpected<E> &e, const expected<T, E> &x) {
2421 return x.has_value() ? false : x.error() == e.value();
2422}
2423template <class T, class E>
2424constexpr bool operator!=(const expected<T, E> &x, const unexpected<E> &e) {
2425 return x.has_value() ? true : x.error() != e.value();
2426}
2427template <class T, class E>
2428constexpr bool operator!=(const unexpected<E> &e, const expected<T, E> &x) {
2429 return x.has_value() ? true : x.error() != e.value();
2430}
2431
2432template <class T, class E,
2433 detail_expected::enable_if_t<(std::is_void<T>::value ||
2434 std::is_move_constructible<T>::value) &&
2435 detail_expected::is_swappable<T>::value &&
2436 std::is_move_constructible<E>::value &&
2437 detail_expected::is_swappable<E>::value> * = nullptr>
2438void swap(expected<T, E> &lhs,
2439 expected<T, E> &rhs) noexcept(noexcept(lhs.swap(rhs))) {
2440 lhs.swap(rhs);
2441}
2442} // namespace wpi
2443
2444#endif
Definition expected:1222
const E & error() const &
Definition expected:1230
bad_expected_access(E e)
Definition expected:1224
E && error() &&
Definition expected:1233
const E && error() const &&
Definition expected:1232
E & error() &
Definition expected:1231
virtual const char * what() const noexcept override
Definition expected:1226
An expected<T, E> object is an object that contains the storage for another object and manages the li...
Definition expected:1250
constexpr expected(unexpect_t, Args &&...args)
Definition expected:1586
constexpr expected(const expected &rhs)=default
expected & operator=(const expected &rhs)=default
WPI_EXPECTED_11_CONSTEXPR U & value() &
Definition expected:1993
constexpr expected(unexpected< G > const &e)
Definition expected:1561
constexpr expected(unexpect_t, std::initializer_list< U > il, Args &&...args)
Definition expected:1593
WPI_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval< expected & >(), std::declval< F && >())) transform_error(F &&f) &
Definition expected:1485
WPI_EXPECTED_11_CONSTEXPR E & error() &
Definition expected:2017
WPI_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval< expected & >(), std::declval< F && >())) map_error(F &&f) &
Definition expected:1442
constexpr const E & error() const &
Definition expected:2013
WPI_EXPECTED_11_CONSTEXPR const U && value() const &&
Definition expected:2000
constexpr bool has_value() const noexcept
Definition expected:1981
constexpr decltype(expected_map_impl(std::declval< const expected & >(), std::declval< F && >())) transform(F &&f) const &
Definition expected:1410
expected & operator=(expected &&rhs)=default
WPI_EXPECTED_11_CONSTEXPR U && operator*() &&
Definition expected:1976
E error_type
Definition expected:1287
WPI_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v)
Definition expected:1660
constexpr decltype(map_error_impl(std::declval< const expected && >(), std::declval< F && >())) map_error(F &&f) const &&
Definition expected:1462
expected WPI_EXPECTED_11_CONSTEXPR or_else(F &&f) &&
Definition expected:1514
WPI_EXPECTED_11_CONSTEXPR const U & value() const &
Definition expected:1986
WPI_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval< expected >(), std::declval< F && >())) transform(F &&f) &&
Definition expected:1404
expected & operator=(U &&v)
Definition expected:1682
WPI_EXPECTED_11_CONSTEXPR expected(const expected< U, G > &rhs)
Definition expected:1604
unexpected< E > unexpected_type
Definition expected:1288
constexpr decltype(expected_map_impl(std::declval< const expected & >(), std::declval< F && >())) map(F &&f) const &
Definition expected:1366
constexpr auto and_then(F &&f) const &-> decltype(and_then_impl(std::declval< expected const & >(), std::forward< F >(f)))
Definition expected:1322
void emplace(Args &&...args)
Definition expected:1762
WPI_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval< expected && >(), std::declval< F && >())) transform_error(F &&f) &&
Definition expected:1491
constexpr decltype(map_error_impl(std::declval< const expected && >(), std::declval< F && >())) transform_error(F &&f) const &&
Definition expected:1505
detail_expected::enable_if_t< detail_expected::is_swappable< OT >::value &&detail_expected::is_swappable< OE >::value &&(std::is_nothrow_move_constructible< OT >::value||std::is_nothrow_move_constructible< OE >::value)> swap(expected &rhs) noexcept(std::is_nothrow_move_constructible< T >::value &&detail_expected::is_nothrow_swappable< T >::value &&std::is_nothrow_move_constructible< E >::value &&detail_expected::is_nothrow_swappable< E >::value)
Definition expected:1930
constexpr decltype(expected_map_impl(std::declval< const expected && >(), std::declval< F && >())) transform(F &&f) const &&
Definition expected:1418
WPI_EXPECTED_11_CONSTEXPR U && value() &&
Definition expected:2007
constexpr const U && operator*() const &&
Definition expected:1970
WPI_EXPECTED_11_CONSTEXPR expected(expected< U, G > &&rhs)
Definition expected:1633
constexpr expected(in_place_t, std::initializer_list< U > il, Args &&...args)
Definition expected:1543
void emplace(std::initializer_list< U > il, Args &&...args)
Definition expected:1800
WPI_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval< expected & >(), std::declval< F && >())) map(F &&f) &
Definition expected:1354
expected & operator=(unexpected< G > &&rhs) noexcept
Definition expected:1748
expected constexpr or_else(F &&f) const &&
Definition expected:1523
constexpr auto and_then(F &&f) const &&-> decltype(and_then_impl(std::declval< expected const && >(), std::forward< F >(f)))
Definition expected:1329
expected & operator=(const unexpected< G > &rhs)
Definition expected:1733
constexpr decltype(map_error_impl(std::declval< const expected & >(), std::declval< F && >())) transform_error(F &&f) const &
Definition expected:1497
WPI_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval< expected & >(), std::declval< F && >())) transform(F &&f) &
Definition expected:1398
WPI_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval< expected >(), std::declval< F && >())) map(F &&f) &&
Definition expected:1360
constexpr expected(in_place_t, Args &&...args)
Definition expected:1536
WPI_EXPECTED_11_CONSTEXPR E && error() &&
Definition expected:2025
T value_type
Definition expected:1286
WPI_EXPECTED_11_CONSTEXPR T * operator->()
Definition expected:1951
constexpr expected()=default
constexpr T value_or(U &&v) const &
Definition expected:2030
WPI_EXPECTED_11_CONSTEXPR T value_or(U &&v) &&
Definition expected:2036
constexpr const U & operator*() const &
Definition expected:1958
WPI_EXPECTED_11_CONSTEXPR auto and_then(F &&f) &-> decltype(and_then_impl(std::declval< expected & >(), std::forward< F >(f)))
Definition expected:1311
WPI_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval< expected && >(), std::declval< F && >())) map_error(F &&f) &&
Definition expected:1448
constexpr expected(unexpected< G > &&e) noexcept(std::is_nothrow_constructible< E, G && >::value)
Definition expected:1569
WPI_EXPECTED_11_CONSTEXPR auto and_then(F &&f) &&-> decltype(and_then_impl(std::declval< expected && >(), std::forward< F >(f)))
Definition expected:1317
constexpr const E && error() const &&
Definition expected:2021
expected WPI_EXPECTED_11_CONSTEXPR or_else(F &&f) &
Definition expected:1510
expected constexpr or_else(F &&f) const &
Definition expected:1518
constexpr expected(expected &&rhs)=default
constexpr const T * operator->() const
Definition expected:1947
WPI_EXPECTED_11_CONSTEXPR U & operator*() &
Definition expected:1964
constexpr expected(const unexpected< G > &e)
Definition expected:1552
constexpr decltype(expected_map_impl(std::declval< const expected && >(), std::declval< F && >())) map(F &&f) const &&
Definition expected:1374
constexpr decltype(map_error_impl(std::declval< const expected & >(), std::declval< F && >())) map_error(F &&f) const &
Definition expected:1454
Definition expected:134
Definition expected:142
constexpr unexpected(const E &e)
Definition expected:147
constexpr const E & value() const &
Definition expected:162
constexpr const E && value() const &&
Definition expected:165
constexpr unexpected(E &&e)
Definition expected:149
constexpr unexpected(std::initializer_list< U > l, Args &&...args)
Definition expected:159
WPI_EXPECTED_11_CONSTEXPR E & value() &
Definition expected:163
unexpected()=delete
constexpr unexpected(Args &&...args)
Definition expected:153
WPI_EXPECTED_11_CONSTEXPR E && value() &&
Definition expected:164
#define WPI_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)
Definition expected:104
#define WPI_EXPECTED_MSVC2015_CONSTEXPR
Definition expected:36
#define WPI_EXPECTED_11_CONSTEXPR
Definition expected:126
#define WPI_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)
Definition expected:108
#define WPI_ASSERT(x)
Definition expected:60
#define WPI_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T)
Definition expected:106
bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json_pointer.h:931
bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json_pointer.h:956
Allocating channel that is out of range Attempted to reuse an allocated resource A pointer parameter to a method is nullptr Compass manufacturer doesn t match HiTechnic The object is in an incompatible mode Attempted to read AnalogTrigger pulse output Task error
Definition Errors.h:23
Implement std::hash so that hash_code can be used in STL containers.
Definition PointerIntPair.h:280
WPI_BASIC_JSON_TPL_DECLARATION void swap(wpi::WPI_BASIC_JSON_TPL &j1, wpi::WPI_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< wpi::WPI_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< wpi::WPI_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition json.h:5258
std::false_type can_swap(...) noexcept(false)
typename std::remove_const< T >::type remove_const_t
Definition expected:228
typename std::remove_reference< T >::type remove_reference_t
Definition expected:230
typename invoke_result< F, Us... >::type invoke_result_t
Definition expected:317
auto and_then_impl(Exp &&exp, F &&f) -> Ret
Definition expected:2077
typename detail_expected::decay_t< Exp >::value_type exp_t
Definition expected:2045
detail_expected::enable_if_t< std::is_constructible< T, UR >::value && std::is_constructible< E, GR >::value && !std::is_constructible< T, expected< U, G > & >::value && !std::is_constructible< T, expected< U, G > && >::value && !std::is_constructible< T, const expected< U, G > & >::value && !std::is_constructible< T, const expected< U, G > && >::value && !std::is_convertible< expected< U, G > &, T >::value && !std::is_convertible< expected< U, G > &&, T >::value && !std::is_convertible< const expected< U, G > &, T >::value && !std::is_convertible< const expected< U, G > &&, T >::value > expected_enable_from_other
Definition expected:405
typename std::conditional< B, T, F >::type conditional_t
Definition expected:235
typename std::decay< T >::type decay_t
Definition expected:231
constexpr auto invoke(Fn &&f, Args &&...args) noexcept(noexcept(std::mem_fn(f)(std::forward< Args >(args)...))) -> decltype(std::mem_fn(f)(std::forward< Args >(args)...))
Definition expected:287
detail_expected::enable_if_t< std::is_constructible< T, U && >::value && !std::is_same< detail_expected::decay_t< U >, in_place_t >::value && !std::is_same< expected< T, E >, detail_expected::decay_t< U > >::value && !std::is_same< unexpected< E >, detail_expected::decay_t< U > >::value > expected_enable_forward_value
Definition expected:398
constexpr auto expected_map_impl(Exp &&exp, F &&f) -> ret_t< Exp, detail_expected::decay_t< Ret > >
Definition expected:2154
is_void_or< T, std::is_copy_assignable< T > > is_copy_assignable_or_void
Definition expected:429
static constexpr no_init_t no_init
Definition expected:438
is_void_or< T, std::is_copy_constructible< T > > is_copy_constructible_or_void
Definition expected:421
conditional_t< std::is_void< T >::value, std::true_type, U > is_void_or
Definition expected:418
is_void_or< T, std::is_move_assignable< T > > is_move_assignable_or_void
Definition expected:432
typename std::enable_if< E, T >::type enable_if_t
Definition expected:233
WPI_EXPECTED_11_CONSTEXPR void throw_exception(E &&e)
Definition expected:212
is_void_or< T, std::is_move_constructible< T > > is_move_constructible_or_void
Definition expected:425
typename detail_expected::decay_t< Exp >::error_type err_t
Definition expected:2046
auto or_else_impl(Exp &&exp, F &&f) -> Ret
Definition expected:2349
constexpr auto map_error_impl(Exp &&exp, F &&f) -> expected< exp_t< Exp >, detail_expected::decay_t< Ret > >
Definition expected:2266
void construct(std::true_type, T *cur, T *end, Args &&... args)
Definition smart_ptr.hpp:45
T && forward(typename std::remove_reference< T >::type &t) noexcept
Definition utility.hpp:31
Foonathan namespace.
Definition ntcore_cpp.h:26
constexpr bool operator>(const unexpected< E > &lhs, const unexpected< E > &rhs)
Definition expected:192
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
Definition PointerIntPair.h:270
unexpected< typename std::decay< E >::type > make_unexpected(E &&e)
Definition expected:201
constexpr bool operator<(const unexpected< E > &lhs, const unexpected< E > &rhs)
Definition expected:184
constexpr bool operator<=(const unexpected< E > &lhs, const unexpected< E > &rhs)
Definition expected:188
static constexpr unexpect_t unexpect
Definition expected:208
bool operator==(const DenseMapBase< DerivedT, KeyT, ValueT, KeyInfoT, BucketT > &LHS, const DenseMapBase< DerivedT, KeyT, ValueT, KeyInfoT, BucketT > &RHS)
Equality comparison for DenseMap.
Definition DenseMap.h:729
static constexpr in_place_t in_place
Definition expected:139
constexpr bool operator>=(const unexpected< E > &lhs, const unexpected< E > &rhs)
Definition expected:196
bool operator!=(const DenseMapBase< DerivedT, KeyT, ValueT, KeyInfoT, BucketT > &LHS, const DenseMapBase< DerivedT, KeyT, ValueT, KeyInfoT, BucketT > &RHS)
Inequality comparison for DenseMap.
Definition DenseMap.h:749
Definition base.h:324
Definition expected:2072
Definition expected:238
expected_copy_assign_base & operator=(const expected_copy_assign_base &rhs)
Definition expected:1020
expected_copy_assign_base(expected_copy_assign_base &&rhs)=default
expected_copy_assign_base(const expected_copy_assign_base &rhs)=default
expected_copy_assign_base & operator=(expected_copy_assign_base &&rhs)=default
expected_copy_base & operator=(expected_copy_base &&rhs)=default
expected_copy_base(expected_copy_base &&rhs)=default
expected_copy_base(const expected_copy_base &rhs)
Definition expected:950
expected_copy_base & operator=(const expected_copy_base &rhs)=default
constexpr expected_default_ctor_base() noexcept=default
expected_delete_assign_base(const expected_delete_assign_base &)=default
expected_delete_assign_base(expected_delete_assign_base &&) noexcept=default
expected_delete_assign_base(const expected_delete_assign_base &)=default
expected_delete_assign_base(expected_delete_assign_base &&) noexcept=default
expected_delete_assign_base(const expected_delete_assign_base &)=default
expected_delete_assign_base(expected_delete_assign_base &&) noexcept=default
expected_delete_assign_base(expected_delete_assign_base &&) noexcept=default
expected_delete_assign_base(const expected_delete_assign_base &)=default
expected_delete_ctor_base(const expected_delete_ctor_base &)=delete
expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept=delete
expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept=default
expected_delete_ctor_base(const expected_delete_ctor_base &)=delete
expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept=delete
expected_delete_ctor_base(const expected_delete_ctor_base &)=default
expected_delete_ctor_base(const expected_delete_ctor_base &)=default
expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept=default
expected_move_assign_base(const expected_move_assign_base &rhs)=default
expected_move_assign_base(expected_move_assign_base &&rhs)=default
expected_move_assign_base & operator=(expected_move_assign_base &&rhs) noexcept(std::is_nothrow_move_constructible< T >::value &&std::is_nothrow_move_assignable< T >::value)
Definition expected:1063
expected_move_assign_base & operator=(const expected_move_assign_base &rhs)=default
expected_move_base(const expected_move_base &rhs)=default
expected_move_base & operator=(expected_move_base &&rhs)=default
expected_move_base & operator=(const expected_move_base &rhs)=default
expected_move_base(expected_move_base &&rhs) noexcept(std::is_nothrow_move_constructible< T >::value)
Definition expected:986
void assign(Rhs &&rhs) noexcept
Definition expected:900
void construct_with(Rhs &&) noexcept
Definition expected:890
constexpr const unexpected< E > & geterr() const &
Definition expected:920
WPI_EXPECTED_11_CONSTEXPR void destroy_val()
Definition expected:930
WPI_EXPECTED_11_CONSTEXPR unexpected< E > & geterr() &
Definition expected:917
void construct() noexcept
Definition expected:886
void construct_error(Args &&...args) noexcept
Definition expected:894
WPI_EXPECTED_11_CONSTEXPR unexpected< E > && geterr() &&
Definition expected:921
constexpr const unexpected< E > && geterr() const &&
Definition expected:925
WPI_EXPECTED_11_CONSTEXPR unexpected< E > & geterr() &
Definition expected:864
constexpr const T && get() const &&
Definition expected:861
WPI_EXPECTED_11_CONSTEXPR void destroy_val()
Definition expected:877
void construct(Args &&...args) noexcept
Definition expected:700
WPI_EXPECTED_11_CONSTEXPR unexpected< E > && geterr() &&
Definition expected:868
void construct_error(Args &&...args) noexcept
Definition expected:710
bool has_value() const
Definition expected:855
void construct_with(Rhs &&rhs) noexcept
Definition expected:705
WPI_EXPECTED_11_CONSTEXPR T & get() &
Definition expected:857
void assign(expected_operations_base &&rhs) noexcept
Definition expected:828
void assign(const expected_operations_base &rhs) noexcept
Definition expected:819
constexpr const unexpected< E > & geterr() const &
Definition expected:867
constexpr const unexpected< E > && geterr() const &&
Definition expected:872
constexpr const T & get() const &
Definition expected:858
void assign_common(Rhs &&rhs)
Definition expected:840
WPI_EXPECTED_11_CONSTEXPR T && get() &&
Definition expected:859
constexpr expected_storage_base(no_init_t)
Definition expected:583
constexpr expected_storage_base(unexpect_t, std::initializer_list< U > il, Args &&...args)
Definition expected:606
constexpr expected_storage_base(unexpect_t, Args &&...args)
Definition expected:600
constexpr expected_storage_base(in_place_t, Args &&...args)
Definition expected:588
constexpr expected_storage_base(in_place_t, std::initializer_list< U > il, Args &&...args)
Definition expected:594
constexpr expected_storage_base(unexpect_t, std::initializer_list< U > il, Args &&...args)
Definition expected:561
WPI_EXPECTED_MSVC2015_CONSTEXPR expected_storage_base(no_init_t)
Definition expected:537
constexpr expected_storage_base(unexpect_t, Args &&...args)
Definition expected:555
constexpr expected_storage_base(in_place_t, Args &&...args)
Definition expected:543
constexpr expected_storage_base(in_place_t, std::initializer_list< U > il, Args &&...args)
Definition expected:549
constexpr expected_storage_base(unexpect_t, std::initializer_list< U > il, Args &&...args)
Definition expected:520
constexpr expected_storage_base(in_place_t, Args &&...args)
Definition expected:502
constexpr expected_storage_base(unexpect_t, Args &&...args)
Definition expected:514
constexpr expected_storage_base(no_init_t)
Definition expected:497
constexpr expected_storage_base(in_place_t, std::initializer_list< U > il, Args &&...args)
Definition expected:508
constexpr expected_storage_base(in_place_t)
Definition expected:665
constexpr expected_storage_base(unexpect_t, std::initializer_list< U > il, Args &&...args)
Definition expected:676
constexpr expected_storage_base(no_init_t)
Definition expected:663
constexpr expected_storage_base(unexpect_t, Args &&...args)
Definition expected:670
constexpr expected_storage_base(unexpect_t, Args &&...args)
Definition expected:640
constexpr expected_storage_base(unexpect_t, std::initializer_list< U > il, Args &&...args)
Definition expected:646
constexpr expected_storage_base(in_place_t)
Definition expected:635
constexpr expected_storage_base(no_init_t)
Definition expected:633
constexpr expected_storage_base()
Definition expected:449
constexpr expected_storage_base(unexpect_t, std::initializer_list< U > il, Args &&...args)
Definition expected:473
bool m_has_val
Definition expected:490
constexpr expected_storage_base(no_init_t)
Definition expected:450
unexpected< E > m_unexpect
Definition expected:487
constexpr expected_storage_base(unexpect_t, Args &&...args)
Definition expected:467
constexpr expected_storage_base(in_place_t, std::initializer_list< U > il, Args &&...args)
Definition expected:461
~expected_storage_base()
Definition expected:478
constexpr expected_storage_base(in_place_t, Args &&...args)
Definition expected:455
char m_no_init
Definition expected:488
decltype(detail_expected::invoke(std::declval< F >(), std::declval< Us >()...)) type
Definition expected:309
Definition expected:368
Definition expected:437
Definition expected:136
in_place_t()=default
Definition expected:205
unexpect_t()=default
typename std::enable_if< B, T >::type enable_if_t
Definition base.h:297