LIEF: Library to Instrument Executable Formats Version 1.0.0
Loading...
Searching...
No Matches
expected.hpp
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/>.
15
16#ifndef TL_EXPECTED_HPP
17#define TL_EXPECTED_HPP
18
19#define TL_EXPECTED_VERSION_MAJOR 1
20#define TL_EXPECTED_VERSION_MINOR 3
21#define TL_EXPECTED_VERSION_PATCH 1
22
23#include <exception>
24#include <functional>
25#include <type_traits>
26#include <utility>
27
28#if defined(__EXCEPTIONS) || defined(_CPPUNWIND)
29#define TL_EXPECTED_EXCEPTIONS_ENABLED
30#endif
31
32#if (defined(_MSC_VER) && _MSC_VER == 1900)
33#define TL_EXPECTED_MSVC2015
34#define TL_EXPECTED_MSVC2015_CONSTEXPR
35#else
36#define TL_EXPECTED_MSVC2015_CONSTEXPR constexpr
37#endif
38
39#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \
40 !defined(__clang__))
41#define TL_EXPECTED_GCC49
42#endif
43
44#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && \
45 !defined(__clang__))
46#define TL_EXPECTED_GCC54
47#endif
48
49#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && \
50 !defined(__clang__))
51#define TL_EXPECTED_GCC55
52#endif
53
54#ifdef _MSVC_LANG
55#define TL_CPLUSPLUS _MSVC_LANG
56#else
57#define TL_CPLUSPLUS __cplusplus
58#endif
59
60#if !defined(TL_ASSERT)
61//can't have assert in constexpr in C++11 and GCC 4.9 has a compiler bug
62#if (TL_CPLUSPLUS > 201103L) && !defined(TL_EXPECTED_GCC49)
63#include <cassert>
64#define TL_ASSERT(x) assert(x)
65#else
66#define TL_ASSERT(x)
67#endif
68#endif
69
70#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \
71 !defined(__clang__))
72// GCC < 5 doesn't support overloading on const&& for member functions
73
74#define TL_EXPECTED_NO_CONSTRR
75// GCC < 5 doesn't support some standard C++11 type traits
76#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
77 std::has_trivial_copy_constructor<T>
78#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
79 std::has_trivial_copy_assign<T>
80
81// This one will be different for GCC 5.7 if it's ever supported
82#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \
83 std::is_trivially_destructible<T>
84
85// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks
86// std::vector for non-copyable types
87#elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__))
88#ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
89#define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
90namespace tl {
91namespace detail {
92template <class T>
93struct is_trivially_copy_constructible
94 : std::is_trivially_copy_constructible<T> {};
95#ifdef _GLIBCXX_VECTOR
96template <class T, class A>
97struct is_trivially_copy_constructible<std::vector<T, A>> : std::false_type {};
98#endif
99} // namespace detail
100} // namespace tl
101#endif
102
103#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
104 tl::detail::is_trivially_copy_constructible<T>
105#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
106 std::is_trivially_copy_assignable<T>
107#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \
108 std::is_trivially_destructible<T>
109#else
110#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
111 std::is_trivially_copy_constructible<T>
112#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
113 std::is_trivially_copy_assignable<T>
114#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \
115 std::is_trivially_destructible<T>
116#endif
117
118#if TL_CPLUSPLUS > 201103L
119#define TL_EXPECTED_CXX14
120#endif
121
122#ifdef TL_EXPECTED_GCC49
123#define TL_EXPECTED_GCC49_CONSTEXPR
124#else
125#define TL_EXPECTED_GCC49_CONSTEXPR constexpr
126#endif
127
128#if (TL_CPLUSPLUS == 201103L || defined(TL_EXPECTED_MSVC2015) || \
129 defined(TL_EXPECTED_GCC49))
130#define TL_EXPECTED_11_CONSTEXPR
131#else
132#define TL_EXPECTED_11_CONSTEXPR constexpr
133#endif
134
135#if TL_CPLUSPLUS >= 201703L
136#define TL_EXPECTED_NODISCARD [[nodiscard]]
137#else
138#define TL_EXPECTED_NODISCARD
139#endif
140
141namespace tl {
142template <class T, class E> class TL_EXPECTED_NODISCARD expected;
143
144#ifndef TL_MONOSTATE_INPLACE_MUTEX
145#define TL_MONOSTATE_INPLACE_MUTEX
146class monostate {};
147
149 explicit in_place_t() = default;
150};
151static constexpr in_place_t in_place{};
152#endif
153
154template <class E> class unexpected {
155public:
156 static_assert(!std::is_same<E, void>::value, "E must not be void");
157
158 unexpected() = delete;
159 constexpr explicit unexpected(const E &e) : m_val(e) {}
160
161 constexpr explicit unexpected(E &&e) : m_val(std::move(e)) {}
162
163 template <class... Args, typename std::enable_if<std::is_constructible<
164 E, Args &&...>::value>::type * = nullptr>
165 constexpr explicit unexpected(Args &&...args)
166 : m_val(std::forward<Args>(args)...) {}
167 template <
168 class U, class... Args,
169 typename std::enable_if<std::is_constructible<
170 E, std::initializer_list<U> &, Args &&...>::value>::type * = nullptr>
171 constexpr explicit unexpected(std::initializer_list<U> l, Args &&...args)
172 : m_val(l, std::forward<Args>(args)...) {}
173
174 constexpr const E &value() const & { return m_val; }
175 TL_EXPECTED_11_CONSTEXPR E &value() & { return m_val; }
176 TL_EXPECTED_11_CONSTEXPR E &&value() && { return std::move(m_val); }
177 constexpr const E &&value() const && { return std::move(m_val); }
178
179private:
180 E m_val;
181};
182
183#ifdef __cpp_deduction_guides
184template <class E> unexpected(E) -> unexpected<E>;
185#endif
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}
199template <class E>
200constexpr bool operator<=(const unexpected<E> &lhs, const unexpected<E> &rhs) {
201 return lhs.value() <= rhs.value();
202}
203template <class E>
204constexpr bool operator>(const unexpected<E> &lhs, const unexpected<E> &rhs) {
205 return lhs.value() > rhs.value();
206}
207template <class E>
208constexpr bool operator>=(const unexpected<E> &lhs, const unexpected<E> &rhs) {
209 return lhs.value() >= rhs.value();
210}
211
212template <class E>
216
218 unexpect_t() = default;
219};
220static constexpr unexpect_t unexpect{};
221
222#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
223#define TL_EXPECTED_THROW_EXCEPTION(e) throw((e));
224#else
225#define TL_EXPECTED_THROW_EXCEPTION(e) std::terminate();
226#endif
227
228namespace detail {
229#ifndef TL_TRAITS_MUTEX
230#define TL_TRAITS_MUTEX
231// C++14-style aliases for brevity
232template <class T> using remove_const_t = typename std::remove_const<T>::type;
233template <class T>
234using remove_reference_t = typename std::remove_reference<T>::type;
235template <class T> using decay_t = typename std::decay<T>::type;
236template <bool E, class T = void>
237using enable_if_t = typename std::enable_if<E, T>::type;
238template <bool B, class T, class F>
239using conditional_t = typename std::conditional<B, T, F>::type;
240
241// std::conjunction from C++17
242template <class...> struct conjunction : std::true_type {};
243template <class B> struct conjunction<B> : B {};
244template <class B, class... Bs>
245struct conjunction<B, Bs...>
246 : std::conditional<bool(B::value), conjunction<Bs...>, B>::type {};
247
248#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L
249#define TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
250#endif
251
252// In C++11 mode, there's an issue in libc++'s std::mem_fn
253// which results in a hard-error when using it in a noexcept expression
254// in some cases. This is a check to workaround the common failing case.
255#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
256template <class T>
257struct is_pointer_to_non_const_member_func : std::false_type {};
258template <class T, class Ret, class... Args>
259struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...)>
260 : std::true_type {};
261template <class T, class Ret, class... Args>
262struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) &>
263 : std::true_type {};
264template <class T, class Ret, class... Args>
265struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) &&>
266 : std::true_type {};
267template <class T, class Ret, class... Args>
268struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile>
269 : std::true_type {};
270template <class T, class Ret, class... Args>
271struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile &>
272 : std::true_type {};
273template <class T, class Ret, class... Args>
274struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile &&>
275 : std::true_type {};
276
277template <class T> struct is_const_or_const_ref : std::false_type {};
278template <class T> struct is_const_or_const_ref<T const &> : std::true_type {};
279template <class T> struct is_const_or_const_ref<T const> : std::true_type {};
280#endif
281
282// std::invoke from C++17
283// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround
284template <
285 typename Fn, typename... Args,
286#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
287 typename = enable_if_t<!(is_pointer_to_non_const_member_func<Fn>::value &&
288 is_const_or_const_ref<Args...>::value)>,
289#endif
290 typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>, int = 0>
291constexpr auto invoke(Fn &&f, Args &&...args) noexcept(
292 noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))
293 -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) {
294 return std::mem_fn(f)(std::forward<Args>(args)...);
295}
296
297template <typename Fn, typename... Args,
299constexpr auto invoke(Fn &&f, Args &&...args) noexcept(
300 noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))
301 -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) {
302 return std::forward<Fn>(f)(std::forward<Args>(args)...);
303}
304
305// std::invoke_result from C++17
306template <class F, class, class... Us> struct invoke_result_impl;
307
308template <class F, class... Us>
310 F,
311 decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...), void()),
312 Us...> {
313 using type =
314 decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...));
315};
316
317template <class F, class... Us>
318using invoke_result = invoke_result_impl<F, void, Us...>;
319
320template <class F, class... Us>
321using invoke_result_t = typename invoke_result<F, Us...>::type;
322
323#if defined(_MSC_VER) && _MSC_VER <= 1900
324// TODO make a version which works with MSVC 2015
325template <class T, class U = T> struct is_swappable : std::true_type {};
326
327template <class T, class U = T> struct is_nothrow_swappable : std::true_type {};
328#else
329// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept
330namespace swap_adl_tests {
331// if swap ADL finds this then it would call std::swap otherwise (same
332// signature)
333struct tag {};
334
335template <class T> tag swap(T &, T &);
336template <class T, std::size_t N> tag swap(T (&a)[N], T (&b)[N]);
337
338// helper functions to test if an unqualified swap is possible, and if it
339// becomes std::swap
340template <class, class> std::false_type can_swap(...) noexcept(false);
341template <class T, class U,
342 class = decltype(swap(std::declval<T &>(), std::declval<U &>()))>
343std::true_type can_swap(int) noexcept(noexcept(swap(std::declval<T &>(),
344 std::declval<U &>())));
345
346template <class, class> std::false_type uses_std(...);
347template <class T, class U>
348std::is_same<decltype(swap(std::declval<T &>(), std::declval<U &>())), tag>
350
351template <class T>
353 : std::integral_constant<bool,
354 std::is_nothrow_move_constructible<T>::value &&
355 std::is_nothrow_move_assignable<T>::value> {};
356
357template <class T, std::size_t N>
359
360template <class T, class U>
362 : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};
363} // namespace swap_adl_tests
364
365template <class T, class U = T>
367 : std::integral_constant<
368 bool,
369 decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&
370 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||
371 (std::is_move_assignable<T>::value &&
372 std::is_move_constructible<T>::value))> {};
373
374template <class T, std::size_t N>
375struct is_swappable<T[N], T[N]>
376 : std::integral_constant<
377 bool,
378 decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&
379 (!decltype(detail::swap_adl_tests::uses_std<T[N], T[N]>(
380 0))::value ||
381 is_swappable<T, T>::value)> {};
382
383template <class T, class U = T>
385 : std::integral_constant<
386 bool,
387 is_swappable<T, U>::value &&
388 ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
389 detail::swap_adl_tests::is_std_swap_noexcept<T>::value) ||
390 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
391 detail::swap_adl_tests::is_adl_swap_noexcept<T, U>::value))> {};
392#endif
393#endif
394
395// Trait for checking if a type is a tl::expected
396template <class T> struct is_expected_impl : std::false_type {};
397template <class T, class E>
398struct is_expected_impl<expected<T, E>> : std::true_type {};
399template <class T> using is_expected = is_expected_impl<decay_t<T>>;
400
401template <class T, class E, class U>
403 std::is_constructible<T, U &&>::value &&
404 !std::is_same<detail::decay_t<U>, in_place_t>::value &&
405 !std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
406 !std::is_same<unexpected<E>, detail::decay_t<U>>::value>;
407
408template <class T, class E, class U, class G, class UR, class GR>
410 std::is_constructible<T, UR>::value &&
411 std::is_constructible<E, GR>::value &&
412 !std::is_constructible<T, expected<U, G> &>::value &&
413 !std::is_constructible<T, expected<U, G> &&>::value &&
414 !std::is_constructible<T, const expected<U, G> &>::value &&
415 !std::is_constructible<T, const expected<U, G> &&>::value &&
416 !std::is_convertible<expected<U, G> &, T>::value &&
417 !std::is_convertible<expected<U, G> &&, T>::value &&
418 !std::is_convertible<const expected<U, G> &, T>::value &&
419 !std::is_convertible<const expected<U, G> &&, T>::value>;
420
421template <class T, class U>
423
424template <class T>
427
428template <class T>
431
432template <class T>
434
435template <class T>
437
438} // namespace detail
439
440namespace detail {
441struct no_init_t {};
442static constexpr no_init_t no_init{};
443
444// Implements the storage of the values, and ensures that the destructor is
445// trivial if it can be.
446//
447// This specialization is for where neither `T` or `E` is trivially
448// destructible, so the destructors must be called on destruction of the
449// `expected`
450template <class T, class E, bool = std::is_trivially_destructible<T>::value,
451 bool = std::is_trivially_destructible<E>::value>
453 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
455
456 template <class... Args,
457 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
458 nullptr>
459 constexpr expected_storage_base(in_place_t, Args &&...args)
460 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
461
462 template <class U, class... Args,
463 detail::enable_if_t<std::is_constructible<
464 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
465 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
466 Args &&...args)
467 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
468 template <class... Args,
469 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
470 nullptr>
471 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
472 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
473
474 template <class U, class... Args,
475 detail::enable_if_t<std::is_constructible<
476 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
478 std::initializer_list<U> il,
479 Args &&...args)
480 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
481
483 if (m_has_val) {
484 m_val.~T();
485 } else {
486 m_unexpect.~unexpected<E>();
487 }
488 }
489 union {
493 };
495};
496
497// This specialization is for when both `T` and `E` are trivially-destructible,
498// so the destructor of the `expected` can be trivial.
499template <class T, class E> struct expected_storage_base<T, E, true, true> {
500 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
502
503 template <class... Args,
504 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
505 nullptr>
506 constexpr expected_storage_base(in_place_t, Args &&...args)
507 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
508
509 template <class U, class... Args,
510 detail::enable_if_t<std::is_constructible<
511 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
512 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
513 Args &&...args)
514 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
515 template <class... Args,
516 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
517 nullptr>
518 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
519 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
520
521 template <class U, class... Args,
522 detail::enable_if_t<std::is_constructible<
523 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
525 std::initializer_list<U> il,
526 Args &&...args)
527 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
528
534 union {
538 };
540};
541
542// T is trivial, E is not.
543template <class T, class E> struct expected_storage_base<T, E, true, false> {
544 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
547
548 template <class... Args,
549 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
550 nullptr>
551 constexpr expected_storage_base(in_place_t, Args &&...args)
552 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
553
554 template <class U, class... Args,
555 detail::enable_if_t<std::is_constructible<
556 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
557 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
558 Args &&...args)
559 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
560 template <class... Args,
561 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
562 nullptr>
563 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
564 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
565
566 template <class U, class... Args,
567 detail::enable_if_t<std::is_constructible<
568 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
570 std::initializer_list<U> il,
571 Args &&...args)
572 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
573
579 if (!m_has_val) {
580 m_unexpect.~unexpected<E>();
581 }
582 }
583
584 union {
588 };
590};
591
592// E is trivial, T is not.
593template <class T, class E> struct expected_storage_base<T, E, false, true> {
594 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
596
597 template <class... Args,
598 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
599 nullptr>
600 constexpr expected_storage_base(in_place_t, Args &&...args)
601 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
602
603 template <class U, class... Args,
604 detail::enable_if_t<std::is_constructible<
605 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
606 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
607 Args &&...args)
608 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
609 template <class... Args,
610 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
611 nullptr>
612 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
613 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
614
615 template <class U, class... Args,
616 detail::enable_if_t<std::is_constructible<
617 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
619 std::initializer_list<U> il,
620 Args &&...args)
621 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
622
628 if (m_has_val) {
629 m_val.~T();
630 }
631 }
632 union {
636 };
638};
639
640// `T` is `void`, `E` is trivially-destructible
642 #if __GNUC__ <= 5
643 //no constexpr for GCC 4/5 bug
644 #else
646 #endif
648
650
652
653 template <class... Args,
654 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
655 nullptr>
656 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
657 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
658
659 template <class U, class... Args,
660 detail::enable_if_t<std::is_constructible<
661 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
663 std::initializer_list<U> il,
664 Args &&...args)
665 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
666
672 struct dummy {};
673 union {
676 };
678};
679
680// `T` is `void`, `E` is not trivially-destructible
682 constexpr expected_storage_base() : m_dummy(), m_has_val(true) {}
684
686
687 template <class... Args,
688 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
689 nullptr>
690 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
691 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
692
693 template <class U, class... Args,
694 detail::enable_if_t<std::is_constructible<
695 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
697 std::initializer_list<U> il,
698 Args &&...args)
699 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
700
706 if (!m_has_val) {
707 m_unexpect.~unexpected<E>();
708 }
709 }
710
711 union {
714 };
716};
717
718// This base class provides some handy member functions which can be used in
719// further derived classes
720template <class T, class E>
723
724 template <class... Args> void construct(Args &&...args) noexcept {
725 new (std::addressof(this->m_val)) T(std::forward<Args>(args)...);
726 this->m_has_val = true;
727 }
728
729 template <class Rhs> void construct_with(Rhs &&rhs) noexcept {
730 new (std::addressof(this->m_val)) T(std::forward<Rhs>(rhs).get());
731 this->m_has_val = true;
732 }
733
734 template <class... Args> void construct_error(Args &&...args) noexcept {
735 new (std::addressof(this->m_unexpect))
736 unexpected<E>(std::forward<Args>(args)...);
737 this->m_has_val = false;
738 }
739
740#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
741
742 // These assign overloads ensure that the most efficient assignment
743 // implementation is used while maintaining the strong exception guarantee.
744 // The problematic case is where rhs has a value, but *this does not.
745 //
746 // This overload handles the case where we can just copy-construct `T`
747 // directly into place without throwing.
748 template <class U = T,
750 * = nullptr>
751 void assign(const expected_operations_base &rhs) noexcept {
752 if (!this->m_has_val && rhs.m_has_val) {
753 geterr().~unexpected<E>();
754 construct(rhs.get());
755 } else {
756 assign_common(rhs);
757 }
758 }
759
760 // This overload handles the case where we can attempt to create a copy of
761 // `T`, then no-throw move it into place if the copy was successful.
762 template <class U = T,
763 detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
764 std::is_nothrow_move_constructible<U>::value>
765 * = nullptr>
766 void assign(const expected_operations_base &rhs) noexcept {
767 if (!this->m_has_val && rhs.m_has_val) {
768 T tmp = rhs.get();
769 geterr().~unexpected<E>();
770 construct(std::move(tmp));
771 } else {
772 assign_common(rhs);
773 }
774 }
775
776 // This overload is the worst-case, where we have to move-construct the
777 // unexpected value into temporary storage, then try to copy the T into place.
778 // If the construction succeeds, then everything is fine, but if it throws,
779 // then we move the old unexpected value back into place before rethrowing the
780 // exception.
781 template <class U = T,
782 detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
783 !std::is_nothrow_move_constructible<U>::value>
784 * = nullptr>
785 void assign(const expected_operations_base &rhs) {
786 if (!this->m_has_val && rhs.m_has_val) {
787 auto tmp = std::move(geterr());
788 geterr().~unexpected<E>();
789
790#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
791 try {
792 construct(rhs.get());
793 } catch (...) {
794 geterr() = std::move(tmp);
795 throw;
796 }
797#else
798 construct(rhs.get());
799#endif
800 } else {
801 assign_common(rhs);
802 }
803 }
804
805 // These overloads do the same as above, but for rvalues
806 template <class U = T,
807 detail::enable_if_t<std::is_nothrow_move_constructible<U>::value>
808 * = nullptr>
809 void assign(expected_operations_base &&rhs) noexcept {
810 if (!this->m_has_val && rhs.m_has_val) {
811 geterr().~unexpected<E>();
812 construct(std::move(rhs).get());
813 } else {
814 assign_common(std::move(rhs));
815 }
816 }
817
818 template <class U = T,
819 detail::enable_if_t<!std::is_nothrow_move_constructible<U>::value>
820 * = nullptr>
821 void assign(expected_operations_base &&rhs) {
822 if (!this->m_has_val && rhs.m_has_val) {
823 auto tmp = std::move(geterr());
824 geterr().~unexpected<E>();
825#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
826 try {
827 construct(std::move(rhs).get());
828 } catch (...) {
829 geterr() = std::move(tmp);
830 throw;
831 }
832#else
833 construct(std::move(rhs).get());
834#endif
835 } else {
836 assign_common(std::move(rhs));
837 }
838 }
839
840#else
841
842 // If exceptions are disabled then we can just copy-construct
843 void assign(const expected_operations_base &rhs) noexcept {
844 if (!this->m_has_val && rhs.m_has_val) {
845 geterr().~unexpected<E>();
846 construct(rhs.get());
847 } else {
848 assign_common(rhs);
849 }
850 }
851
852 void assign(expected_operations_base &&rhs) noexcept {
853 if (!this->m_has_val && rhs.m_has_val) {
854 geterr().~unexpected<E>();
855 construct(std::move(rhs).get());
856 } else {
857 assign_common(std::move(rhs));
858 }
859 }
860
861#endif
862
863 // The common part of move/copy assigning
864 template <class Rhs> void assign_common(Rhs &&rhs) {
865 if (this->m_has_val) {
866 if (rhs.m_has_val) {
867 get() = std::forward<Rhs>(rhs).get();
868 } else {
869 destroy_val();
870 construct_error(std::forward<Rhs>(rhs).geterr());
871 }
872 } else {
873 if (!rhs.m_has_val) {
874 geterr() = std::forward<Rhs>(rhs).geterr();
875 }
876 }
877 }
878
879 bool has_value() const { return this->m_has_val; }
880
881 TL_EXPECTED_11_CONSTEXPR T &get() & { return this->m_val; }
882 constexpr const T &get() const & { return this->m_val; }
883 TL_EXPECTED_11_CONSTEXPR T &&get() && { return std::move(this->m_val); }
884#ifndef TL_EXPECTED_NO_CONSTRR
885 constexpr const T &&get() const && { return std::move(this->m_val); }
886#endif
887
891 constexpr const unexpected<E> &geterr() const & { return this->m_unexpect; }
893 return std::move(this->m_unexpect);
894 }
895#ifndef TL_EXPECTED_NO_CONSTRR
896 constexpr const unexpected<E> &&geterr() const && {
897 return std::move(this->m_unexpect);
898 }
899#endif
900
902};
903
904// This base class provides some handy member functions which can be used in
905// further derived classes
906template <class E>
909
910 template <class... Args> void construct() noexcept { this->m_has_val = true; }
911
912 // This function doesn't use its argument, but needs it so that code in
913 // levels above this can work independently of whether T is void
914 template <class Rhs> void construct_with(Rhs &&) noexcept {
915 this->m_has_val = true;
916 }
917
918 template <class... Args> void construct_error(Args &&...args) noexcept {
919 new (std::addressof(this->m_unexpect))
920 unexpected<E>(std::forward<Args>(args)...);
921 this->m_has_val = false;
922 }
923
924 template <class Rhs> void assign(Rhs &&rhs) noexcept {
925 if (!this->m_has_val) {
926 if (rhs.m_has_val) {
927 geterr().~unexpected<E>();
928 construct();
929 } else {
930 geterr() = std::forward<Rhs>(rhs).geterr();
931 }
932 } else {
933 if (!rhs.m_has_val) {
934 construct_error(std::forward<Rhs>(rhs).geterr());
935 }
936 }
937 }
938
939 bool has_value() const { return this->m_has_val; }
940
944 constexpr const unexpected<E> &geterr() const & { return this->m_unexpect; }
946 return std::move(this->m_unexpect);
947 }
948#ifndef TL_EXPECTED_NO_CONSTRR
949 constexpr const unexpected<E> &&geterr() const && {
950 return std::move(this->m_unexpect);
951 }
952#endif
953
955 // no-op
956 }
957};
958
959// This class manages conditionally having a trivial copy constructor
960// This specialization is for when T and E are trivially copy constructible
961template <class T, class E,
964 bool = (is_copy_constructible_or_void<T>::value &&
965 std::is_copy_constructible<E>::value)>
969
970// This specialization is for when T or E are non-trivially copy constructible
971template <class T, class E>
974
977 : expected_operations_base<T, E>(no_init) {
978 if (rhs.has_value()) {
979 this->construct_with(rhs);
980 } else {
981 this->construct_error(rhs.geterr());
982 }
983 }
984
988};
989
990// This class manages conditionally having a trivial move constructor
991// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
992// doesn't implement an analogue to std::is_trivially_move_constructible. We
993// have to make do with a non-trivial move constructor even if T is trivially
994// move constructible
995#ifndef TL_EXPECTED_GCC49
996template <class T, class E,
998 &&std::is_trivially_move_constructible<E>::value>
1002#else
1003template <class T, class E, bool = false> struct expected_move_base;
1004#endif
1005template <class T, class E>
1006struct expected_move_base<T, E, false> : expected_copy_base<T, E> {
1008
1011
1013 std::is_nothrow_move_constructible<T>::value)
1014 : expected_copy_base<T, E>(no_init) {
1015 if (rhs.has_value()) {
1016 this->construct_with(std::move(rhs));
1017 } else {
1018 this->construct_error(std::move(rhs.geterr()));
1019 }
1020 }
1023};
1024
1025// This class manages conditionally having a trivial copy assignment operator
1026template <class T, class E,
1027 bool = is_void_or<
1034 bool = (is_copy_constructible_or_void<T>::value &&
1035 std::is_copy_constructible<E>::value &&
1036 is_copy_assignable_or_void<T>::value &&
1037 std::is_copy_assignable<E>::value)>
1041
1042template <class T, class E>
1057
1058// This class manages conditionally having a trivial move assignment operator
1059// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
1060// doesn't implement an analogue to std::is_trivially_move_assignable. We have
1061// to make do with a non-trivial move assignment operator even if T is trivially
1062// move assignable
1063#ifndef TL_EXPECTED_GCC49
1064template <class T, class E,
1065 bool =
1067 std::is_trivially_move_constructible<T>,
1068 std::is_trivially_move_assignable<T>>>::
1069 value &&std::is_trivially_destructible<E>::value
1070 &&std::is_trivially_move_constructible<E>::value
1071 &&std::is_trivially_move_assignable<E>::value>
1075#else
1076template <class T, class E, bool = false> struct expected_move_assign_base;
1077#endif
1078
1079template <class T, class E>
1080struct expected_move_assign_base<T, E, false>
1083
1086
1088
1091
1094 std::is_nothrow_move_constructible<T>::value
1095 &&std::is_nothrow_move_assignable<T>::value) {
1096 this->assign(std::move(rhs));
1097 return *this;
1098 }
1099};
1100
1101// expected_delete_ctor_base will conditionally delete copy and move
1102// constructors depending on whether T is copy/move constructible
1103template <class T, class E,
1104 bool EnableCopy = (is_copy_constructible_or_void<T>::value &&
1105 std::is_copy_constructible<E>::value),
1106 bool EnableMove = (is_move_constructible_or_void<T>::value &&
1107 std::is_move_constructible<E>::value)>
1117
1118template <class T, class E>
1128
1129template <class T, class E>
1139
1140template <class T, class E>
1150
1151// expected_delete_assign_base will conditionally delete copy and move
1152// constructors depending on whether T and E are copy/move constructible +
1153// assignable
1154template <class T, class E,
1155 bool EnableCopy = (is_copy_constructible_or_void<T>::value &&
1156 std::is_copy_constructible<E>::value &&
1157 is_copy_assignable_or_void<T>::value &&
1158 std::is_copy_assignable<E>::value),
1159 bool EnableMove = (is_move_constructible_or_void<T>::value &&
1160 std::is_move_constructible<E>::value &&
1161 is_move_assignable_or_void<T>::value &&
1162 std::is_move_assignable<E>::value)>
1173
1174template <class T, class E>
1185
1186template <class T, class E>
1197
1198template <class T, class E>
1209
1210// This is needed to be able to construct the expected_default_ctor_base which
1211// follows, while still conditionally deleting the default constructor.
1213 explicit constexpr default_constructor_tag() = default;
1214};
1215
1216// expected_default_ctor_base will ensure that expected has a deleted default
1217// constructor if T is not default constructible.
1218// This specialization is for when T is default constructible
1219template <class T, class E,
1220 bool Enable =
1221 std::is_default_constructible<T>::value || std::is_void<T>::value>
1223 constexpr expected_default_ctor_base() noexcept = default;
1225 expected_default_ctor_base const &) noexcept = default;
1227 default;
1229 operator=(expected_default_ctor_base const &) noexcept = default;
1231 operator=(expected_default_ctor_base &&) noexcept = default;
1232
1234};
1235
1236// This specialization is for when T is not default constructible
1237template <class T, class E> struct expected_default_ctor_base<T, E, false> {
1238 constexpr expected_default_ctor_base() noexcept = delete;
1240 expected_default_ctor_base const &) noexcept = default;
1242 default;
1244 operator=(expected_default_ctor_base const &) noexcept = default;
1246 operator=(expected_default_ctor_base &&) noexcept = default;
1247
1249};
1250} // namespace detail
1251
1252template <class E> class bad_expected_access : public std::exception {
1253public:
1254 explicit bad_expected_access(E e) : m_val(std::move(e)) {}
1255
1256 virtual const char *what() const noexcept override {
1257 return "Bad expected access";
1258 }
1259
1260 const E &error() const & { return m_val; }
1261 E &error() & { return m_val; }
1262 const E &&error() const && { return std::move(m_val); }
1263 E &&error() && { return std::move(m_val); }
1264
1265private:
1266 E m_val;
1267};
1268
1276template <class T, class E>
1282 static_assert(!std::is_reference<T>::value, "T must not be a reference");
1283 static_assert(!std::is_same<T, std::remove_cv<in_place_t>::type>::value,
1284 "T must not be in_place_t");
1285 static_assert(!std::is_same<T, std::remove_cv<unexpect_t>::type>::value,
1286 "T must not be unexpect_t");
1287 static_assert(
1288 !std::is_same<T, typename std::remove_cv<unexpected<E>>::type>::value,
1289 "T must not be unexpected<E>");
1290 static_assert(!std::is_reference<E>::value, "E must not be a reference");
1291
1292 T *valptr() { return std::addressof(this->m_val); }
1293 const T *valptr() const { return std::addressof(this->m_val); }
1294 unexpected<E> *errptr() { return std::addressof(this->m_unexpect); }
1295 const unexpected<E> *errptr() const {
1296 return std::addressof(this->m_unexpect);
1297 }
1298
1299 template <class U = T,
1301 TL_EXPECTED_11_CONSTEXPR U &val() {
1302 return this->m_val;
1303 }
1304 TL_EXPECTED_11_CONSTEXPR unexpected<E> &err() { return this->m_unexpect; }
1305
1306 template <class U = T,
1308 constexpr const U &val() const {
1309 return this->m_val;
1310 }
1311 constexpr const unexpected<E> &err() const { return this->m_unexpect; }
1312
1315
1316public:
1317 typedef T value_type;
1318 typedef E error_type;
1320
1321#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \
1322 !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)
1323 template <class F> TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & {
1324 return and_then_impl(*this, std::forward<F>(f));
1325 }
1326 template <class F> TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && {
1327 return and_then_impl(std::move(*this), std::forward<F>(f));
1328 }
1329 template <class F> constexpr auto and_then(F &&f) const & {
1330 return and_then_impl(*this, std::forward<F>(f));
1331 }
1332
1333#ifndef TL_EXPECTED_NO_CONSTRR
1334 template <class F> constexpr auto and_then(F &&f) const && {
1335 return and_then_impl(std::move(*this), std::forward<F>(f));
1336 }
1337#endif
1338
1339#else
1340 template <class F>
1342 and_then(F &&f) & -> decltype(and_then_impl(std::declval<expected &>(),
1343 std::forward<F>(f))) {
1344 return and_then_impl(*this, std::forward<F>(f));
1345 }
1346 template <class F>
1348 and_then(F &&f) && -> decltype(and_then_impl(std::declval<expected &&>(),
1349 std::forward<F>(f))) {
1350 return and_then_impl(std::move(*this), std::forward<F>(f));
1351 }
1352 template <class F>
1353 constexpr auto and_then(F &&f) const & -> decltype(and_then_impl(
1354 std::declval<expected const &>(), std::forward<F>(f))) {
1355 return and_then_impl(*this, std::forward<F>(f));
1356 }
1357
1358#ifndef TL_EXPECTED_NO_CONSTRR
1359 template <class F>
1360 constexpr auto and_then(F &&f) const && -> decltype(and_then_impl(
1361 std::declval<expected const &&>(), std::forward<F>(f))) {
1362 return and_then_impl(std::move(*this), std::forward<F>(f));
1363 }
1364#endif
1365#endif
1366
1367#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \
1368 !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)
1369 template <class F> TL_EXPECTED_11_CONSTEXPR auto map(F &&f) & {
1370 return expected_map_impl(*this, std::forward<F>(f));
1371 }
1372 template <class F> TL_EXPECTED_11_CONSTEXPR auto map(F &&f) && {
1373 return expected_map_impl(std::move(*this), std::forward<F>(f));
1374 }
1375 template <class F> constexpr auto map(F &&f) const & {
1376 return expected_map_impl(*this, std::forward<F>(f));
1377 }
1378 template <class F> constexpr auto map(F &&f) const && {
1379 return expected_map_impl(std::move(*this), std::forward<F>(f));
1380 }
1381#else
1382 template <class F>
1384 std::declval<expected &>(), std::declval<F &&>()))
1385 map(F &&f) & {
1386 return expected_map_impl(*this, std::forward<F>(f));
1387 }
1388 template <class F>
1389 TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval<expected>(),
1390 std::declval<F &&>()))
1391 map(F &&f) && {
1392 return expected_map_impl(std::move(*this), std::forward<F>(f));
1393 }
1394 template <class F>
1395 constexpr decltype(expected_map_impl(std::declval<const expected &>(),
1396 std::declval<F &&>()))
1397 map(F &&f) const & {
1398 return expected_map_impl(*this, std::forward<F>(f));
1399 }
1400
1401#ifndef TL_EXPECTED_NO_CONSTRR
1402 template <class F>
1403 constexpr decltype(expected_map_impl(std::declval<const expected &&>(),
1404 std::declval<F &&>()))
1405 map(F &&f) const && {
1406 return expected_map_impl(std::move(*this), std::forward<F>(f));
1407 }
1408#endif
1409#endif
1410
1411#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \
1412 !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)
1413 template <class F> TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) & {
1414 return expected_map_impl(*this, std::forward<F>(f));
1415 }
1416 template <class F> TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) && {
1417 return expected_map_impl(std::move(*this), std::forward<F>(f));
1418 }
1419 template <class F> constexpr auto transform(F &&f) const & {
1420 return expected_map_impl(*this, std::forward<F>(f));
1421 }
1422 template <class F> constexpr auto transform(F &&f) const && {
1423 return expected_map_impl(std::move(*this), std::forward<F>(f));
1424 }
1425#else
1426 template <class F>
1428 std::declval<expected &>(), std::declval<F &&>()))
1429 transform(F &&f) & {
1430 return expected_map_impl(*this, std::forward<F>(f));
1431 }
1432 template <class F>
1433 TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval<expected>(),
1434 std::declval<F &&>()))
1435 transform(F &&f) && {
1436 return expected_map_impl(std::move(*this), std::forward<F>(f));
1437 }
1438 template <class F>
1439 constexpr decltype(expected_map_impl(std::declval<const expected &>(),
1440 std::declval<F &&>()))
1441 transform(F &&f) const & {
1442 return expected_map_impl(*this, std::forward<F>(f));
1443 }
1444
1445#ifndef TL_EXPECTED_NO_CONSTRR
1446 template <class F>
1447 constexpr decltype(expected_map_impl(std::declval<const expected &&>(),
1448 std::declval<F &&>()))
1449 transform(F &&f) const && {
1450 return expected_map_impl(std::move(*this), std::forward<F>(f));
1451 }
1452#endif
1453#endif
1454
1455#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \
1456 !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)
1457 template <class F> TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) & {
1458 return map_error_impl(*this, std::forward<F>(f));
1459 }
1460 template <class F> TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) && {
1461 return map_error_impl(std::move(*this), std::forward<F>(f));
1462 }
1463 template <class F> constexpr auto map_error(F &&f) const & {
1464 return map_error_impl(*this, std::forward<F>(f));
1465 }
1466 template <class F> constexpr auto map_error(F &&f) const && {
1467 return map_error_impl(std::move(*this), std::forward<F>(f));
1468 }
1469#else
1470 template <class F>
1471 TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval<expected &>(),
1472 std::declval<F &&>()))
1473 map_error(F &&f) & {
1474 return map_error_impl(*this, std::forward<F>(f));
1475 }
1476 template <class F>
1477 TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval<expected &&>(),
1478 std::declval<F &&>()))
1479 map_error(F &&f) && {
1480 return map_error_impl(std::move(*this), std::forward<F>(f));
1481 }
1482 template <class F>
1483 constexpr decltype(map_error_impl(std::declval<const expected &>(),
1484 std::declval<F &&>()))
1485 map_error(F &&f) const & {
1486 return map_error_impl(*this, std::forward<F>(f));
1487 }
1488
1489#ifndef TL_EXPECTED_NO_CONSTRR
1490 template <class F>
1491 constexpr decltype(map_error_impl(std::declval<const expected &&>(),
1492 std::declval<F &&>()))
1493 map_error(F &&f) const && {
1494 return map_error_impl(std::move(*this), std::forward<F>(f));
1495 }
1496#endif
1497#endif
1498#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \
1499 !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)
1500 template <class F> TL_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) & {
1501 return map_error_impl(*this, std::forward<F>(f));
1502 }
1503 template <class F> TL_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) && {
1504 return map_error_impl(std::move(*this), std::forward<F>(f));
1505 }
1506 template <class F> constexpr auto transform_error(F &&f) const & {
1507 return map_error_impl(*this, std::forward<F>(f));
1508 }
1509 template <class F> constexpr auto transform_error(F &&f) const && {
1510 return map_error_impl(std::move(*this), std::forward<F>(f));
1511 }
1512#else
1513 template <class F>
1514 TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval<expected &>(),
1515 std::declval<F &&>()))
1517 return map_error_impl(*this, std::forward<F>(f));
1518 }
1519 template <class F>
1520 TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval<expected &&>(),
1521 std::declval<F &&>()))
1523 return map_error_impl(std::move(*this), std::forward<F>(f));
1524 }
1525 template <class F>
1526 constexpr decltype(map_error_impl(std::declval<const expected &>(),
1527 std::declval<F &&>()))
1528 transform_error(F &&f) const & {
1529 return map_error_impl(*this, std::forward<F>(f));
1530 }
1531
1532#ifndef TL_EXPECTED_NO_CONSTRR
1533 template <class F>
1534 constexpr decltype(map_error_impl(std::declval<const expected &&>(),
1535 std::declval<F &&>()))
1536 transform_error(F &&f) const && {
1537 return map_error_impl(std::move(*this), std::forward<F>(f));
1538 }
1539#endif
1540#endif
1541 template <class F> expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) & {
1542 return or_else_impl(*this, std::forward<F>(f));
1543 }
1544
1545 template <class F> expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) && {
1546 return or_else_impl(std::move(*this), std::forward<F>(f));
1547 }
1548
1549 template <class F> expected constexpr or_else(F &&f) const & {
1550 return or_else_impl(*this, std::forward<F>(f));
1551 }
1552
1553#ifndef TL_EXPECTED_NO_CONSTRR
1554 template <class F> expected constexpr or_else(F &&f) const && {
1555 return or_else_impl(std::move(*this), std::forward<F>(f));
1556 }
1557#endif
1558 constexpr expected() = default;
1559 constexpr expected(const expected &rhs) = default;
1560 constexpr expected(expected &&rhs) = default;
1561 expected &operator=(const expected &rhs) = default;
1562 expected &operator=(expected &&rhs) = default;
1563
1564 template <class... Args,
1565 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
1566 nullptr>
1567 constexpr expected(in_place_t, Args &&...args)
1568 : impl_base(in_place, std::forward<Args>(args)...),
1569 ctor_base(detail::default_constructor_tag{}) {}
1570
1571 template <class U, class... Args,
1572 detail::enable_if_t<std::is_constructible<
1573 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
1574 constexpr expected(in_place_t, std::initializer_list<U> il, Args &&...args)
1575 : impl_base(in_place, il, std::forward<Args>(args)...),
1576 ctor_base(detail::default_constructor_tag{}) {}
1577
1578 template <class G = E,
1580 nullptr,
1582 nullptr>
1583 explicit constexpr expected(const unexpected<G> &e)
1584 : impl_base(unexpect, e.value()),
1585 ctor_base(detail::default_constructor_tag{}) {}
1586
1587 template <
1588 class G = E,
1590 nullptr,
1592 constexpr expected(unexpected<G> const &e)
1593 : impl_base(unexpect, e.value()),
1594 ctor_base(detail::default_constructor_tag{}) {}
1595
1596 template <
1597 class G = E,
1600 explicit constexpr expected(unexpected<G> &&e) noexcept(
1601 std::is_nothrow_constructible<E, G &&>::value)
1602 : impl_base(unexpect, std::move(e.value())),
1603 ctor_base(detail::default_constructor_tag{}) {}
1604
1605 template <
1606 class G = E,
1609 constexpr expected(unexpected<G> &&e) noexcept(
1610 std::is_nothrow_constructible<E, G &&>::value)
1611 : impl_base(unexpect, std::move(e.value())),
1612 ctor_base(detail::default_constructor_tag{}) {}
1613
1614 template <class... Args,
1615 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
1616 nullptr>
1617 constexpr explicit expected(unexpect_t, Args &&...args)
1618 : impl_base(unexpect, std::forward<Args>(args)...),
1619 ctor_base(detail::default_constructor_tag{}) {}
1620
1621 template <class U, class... Args,
1622 detail::enable_if_t<std::is_constructible<
1623 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
1624 constexpr explicit expected(unexpect_t, std::initializer_list<U> il,
1625 Args &&...args)
1626 : impl_base(unexpect, il, std::forward<Args>(args)...),
1627 ctor_base(detail::default_constructor_tag{}) {}
1628
1629 template <class U, class G,
1630 detail::enable_if_t<!(std::is_convertible<U const &, T>::value &&
1631 std::is_convertible<G const &, E>::value)> * =
1632 nullptr,
1634 * = nullptr>
1636 : ctor_base(detail::default_constructor_tag{}) {
1637 if (rhs.has_value()) {
1638 this->construct(*rhs);
1639 } else {
1640 this->construct_error(rhs.error());
1641 }
1642 }
1643
1644 template <class U, class G,
1645 detail::enable_if_t<(std::is_convertible<U const &, T>::value &&
1646 std::is_convertible<G const &, E>::value)> * =
1647 nullptr,
1649 * = nullptr>
1651 : ctor_base(detail::default_constructor_tag{}) {
1652 if (rhs.has_value()) {
1653 this->construct(*rhs);
1654 } else {
1655 this->construct_error(rhs.error());
1656 }
1657 }
1658
1659 template <
1660 class U, class G,
1661 detail::enable_if_t<!(std::is_convertible<U &&, T>::value &&
1662 std::is_convertible<G &&, E>::value)> * = nullptr,
1665 : ctor_base(detail::default_constructor_tag{}) {
1666 if (rhs.has_value()) {
1667 this->construct(std::move(*rhs));
1668 } else {
1669 this->construct_error(std::move(rhs.error()));
1670 }
1671 }
1672
1673 template <
1674 class U, class G,
1675 detail::enable_if_t<(std::is_convertible<U &&, T>::value &&
1676 std::is_convertible<G &&, E>::value)> * = nullptr,
1679 : ctor_base(detail::default_constructor_tag{}) {
1680 if (rhs.has_value()) {
1681 this->construct(std::move(*rhs));
1682 } else {
1683 this->construct_error(std::move(rhs.error()));
1684 }
1685 }
1686
1687 template <
1688 class U = T,
1692 : expected(in_place, std::forward<U>(v)) {}
1693
1694 template <
1695 class U = T,
1699 : expected(in_place, std::forward<U>(v)) {}
1700
1701 template <
1702 class U = T, class G = T,
1704 nullptr,
1707 (!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
1709 std::is_same<T, detail::decay_t<U>>>::value &&
1710 std::is_constructible<T, U>::value &&
1711 std::is_assignable<G &, U>::value &&
1712 std::is_nothrow_move_constructible<E>::value)> * = nullptr>
1714 if (has_value()) {
1715 val() = std::forward<U>(v);
1716 } else {
1717 err().~unexpected<E>();
1718 ::new (valptr()) T(std::forward<U>(v));
1719 this->m_has_val = true;
1720 }
1721
1722 return *this;
1723 }
1724
1725 template <
1726 class U = T, class G = T,
1728 nullptr,
1731 (!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
1733 std::is_same<T, detail::decay_t<U>>>::value &&
1734 std::is_constructible<T, U>::value &&
1735 std::is_assignable<G &, U>::value &&
1736 std::is_nothrow_move_constructible<E>::value)> * = nullptr>
1737 expected &operator=(U &&v) {
1738 if (has_value()) {
1739 val() = std::forward<U>(v);
1740 } else {
1741 auto tmp = std::move(err());
1742 err().~unexpected<E>();
1743
1744#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1745 try {
1746 ::new (valptr()) T(std::forward<U>(v));
1747 this->m_has_val = true;
1748 } catch (...) {
1749 err() = std::move(tmp);
1750 throw;
1751 }
1752#else
1753 ::new (valptr()) T(std::forward<U>(v));
1754 this->m_has_val = true;
1755#endif
1756 }
1757
1758 return *this;
1759 }
1760
1761 template <class G = E,
1763 std::is_assignable<G &, G>::value> * = nullptr>
1765 if (!has_value()) {
1766 err() = rhs;
1767 } else {
1768 this->destroy_val();
1769 ::new (errptr()) unexpected<E>(rhs);
1770 this->m_has_val = false;
1771 }
1772
1773 return *this;
1774 }
1775
1776 template <class G = E,
1778 std::is_move_assignable<G>::value> * = nullptr>
1780 if (!has_value()) {
1781 err() = std::move(rhs);
1782 } else {
1783 this->destroy_val();
1784 ::new (errptr()) unexpected<E>(std::move(rhs));
1785 this->m_has_val = false;
1786 }
1787
1788 return *this;
1789 }
1790
1791 template <class... Args, detail::enable_if_t<std::is_nothrow_constructible<
1792 T, Args &&...>::value> * = nullptr>
1793 void emplace(Args &&...args) {
1794 if (has_value()) {
1795 val().~T();
1796 } else {
1797 err().~unexpected<E>();
1798 this->m_has_val = true;
1799 }
1800 ::new (valptr()) T(std::forward<Args>(args)...);
1801 }
1802
1803 template <class... Args, detail::enable_if_t<!std::is_nothrow_constructible<
1804 T, Args &&...>::value> * = nullptr>
1805 void emplace(Args &&...args) {
1806 if (has_value()) {
1807 val().~T();
1808 ::new (valptr()) T(std::forward<Args>(args)...);
1809 } else {
1810 auto tmp = std::move(err());
1811 err().~unexpected<E>();
1812
1813#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1814 try {
1815 ::new (valptr()) T(std::forward<Args>(args)...);
1816 this->m_has_val = true;
1817 } catch (...) {
1818 err() = std::move(tmp);
1819 throw;
1820 }
1821#else
1822 ::new (valptr()) T(std::forward<Args>(args)...);
1823 this->m_has_val = true;
1824#endif
1825 }
1826 }
1827
1828 template <class U, class... Args,
1829 detail::enable_if_t<std::is_nothrow_constructible<
1830 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
1831 void emplace(std::initializer_list<U> il, Args &&...args) {
1832 if (has_value()) {
1833 T t(il, std::forward<Args>(args)...);
1834 val() = std::move(t);
1835 } else {
1836 err().~unexpected<E>();
1837 ::new (valptr()) T(il, std::forward<Args>(args)...);
1838 this->m_has_val = true;
1839 }
1840 }
1841
1842 template <class U, class... Args,
1843 detail::enable_if_t<!std::is_nothrow_constructible<
1844 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
1845 void emplace(std::initializer_list<U> il, Args &&...args) {
1846 if (has_value()) {
1847 T t(il, std::forward<Args>(args)...);
1848 val() = std::move(t);
1849 } else {
1850 auto tmp = std::move(err());
1851 err().~unexpected<E>();
1852
1853#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1854 try {
1855 ::new (valptr()) T(il, std::forward<Args>(args)...);
1856 this->m_has_val = true;
1857 } catch (...) {
1858 err() = std::move(tmp);
1859 throw;
1860 }
1861#else
1862 ::new (valptr()) T(il, std::forward<Args>(args)...);
1863 this->m_has_val = true;
1864#endif
1865 }
1866 }
1867
1868private:
1869 using t_is_void = std::true_type;
1870 using t_is_not_void = std::false_type;
1871 using t_is_nothrow_move_constructible = std::true_type;
1872 using move_constructing_t_can_throw = std::false_type;
1873 using e_is_nothrow_move_constructible = std::true_type;
1874 using move_constructing_e_can_throw = std::false_type;
1875
1876 void swap_where_both_have_value(expected & /*rhs*/, t_is_void) noexcept {
1877 // swapping void is a no-op
1878 }
1879
1880 void swap_where_both_have_value(expected &rhs, t_is_not_void) {
1881 using std::swap;
1882 swap(val(), rhs.val());
1883 }
1884
1885 void swap_where_only_one_has_value(expected &rhs, t_is_void) noexcept(
1886 std::is_nothrow_move_constructible<E>::value) {
1887 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1888 rhs.err().~unexpected_type();
1889 std::swap(this->m_has_val, rhs.m_has_val);
1890 }
1891
1892 void swap_where_only_one_has_value(expected &rhs, t_is_not_void) {
1893 swap_where_only_one_has_value_and_t_is_not_void(
1894 rhs, typename std::is_nothrow_move_constructible<T>::type{},
1895 typename std::is_nothrow_move_constructible<E>::type{});
1896 }
1897
1898 void swap_where_only_one_has_value_and_t_is_not_void(
1899 expected &rhs, t_is_nothrow_move_constructible,
1900 e_is_nothrow_move_constructible) noexcept {
1901 auto temp = std::move(val());
1902 val().~T();
1903 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1904 rhs.err().~unexpected_type();
1905 ::new (rhs.valptr()) T(std::move(temp));
1906 std::swap(this->m_has_val, rhs.m_has_val);
1907 }
1908
1909 void swap_where_only_one_has_value_and_t_is_not_void(
1910 expected &rhs, t_is_nothrow_move_constructible,
1911 move_constructing_e_can_throw) {
1912 auto temp = std::move(val());
1913 val().~T();
1914#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1915 try {
1916 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1917 rhs.err().~unexpected_type();
1918 ::new (rhs.valptr()) T(std::move(temp));
1919 std::swap(this->m_has_val, rhs.m_has_val);
1920 } catch (...) {
1921 val() = std::move(temp);
1922 throw;
1923 }
1924#else
1925 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1926 rhs.err().~unexpected_type();
1927 ::new (rhs.valptr()) T(std::move(temp));
1928 std::swap(this->m_has_val, rhs.m_has_val);
1929#endif
1930 }
1931
1932 void swap_where_only_one_has_value_and_t_is_not_void(
1933 expected &rhs, move_constructing_t_can_throw,
1934 e_is_nothrow_move_constructible) {
1935 auto temp = std::move(rhs.err());
1936 rhs.err().~unexpected_type();
1937#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1938 try {
1939 ::new (rhs.valptr()) T(std::move(val()));
1940 val().~T();
1941 ::new (errptr()) unexpected_type(std::move(temp));
1942 std::swap(this->m_has_val, rhs.m_has_val);
1943 } catch (...) {
1944 rhs.err() = std::move(temp);
1945 throw;
1946 }
1947#else
1948 ::new (rhs.valptr()) T(std::move(val()));
1949 val().~T();
1950 ::new (errptr()) unexpected_type(std::move(temp));
1951 std::swap(this->m_has_val, rhs.m_has_val);
1952#endif
1953 }
1954
1955public:
1956 template <class OT = T, class OE = E>
1957 detail::enable_if_t<detail::is_swappable<OT>::value &&
1958 detail::is_swappable<OE>::value &&
1959 (std::is_nothrow_move_constructible<OT>::value ||
1960 std::is_nothrow_move_constructible<OE>::value)>
1961 swap(expected &rhs) noexcept(
1962 std::is_nothrow_move_constructible<T>::value
1964 &&std::is_nothrow_move_constructible<E>::value
1966 if (has_value() && rhs.has_value()) {
1967 swap_where_both_have_value(rhs, typename std::is_void<T>::type{});
1968 } else if (!has_value() && rhs.has_value()) {
1969 rhs.swap(*this);
1970 } else if (has_value()) {
1971 swap_where_only_one_has_value(rhs, typename std::is_void<T>::type{});
1972 } else {
1973 using std::swap;
1974 swap(err(), rhs.err());
1975 }
1976 }
1977
1978 constexpr const T *operator->() const {
1980 return valptr();
1981 }
1984 return valptr();
1985 }
1986
1987 template <class U = T,
1989 constexpr const U &operator*() const & {
1991 return val();
1992 }
1993 template <class U = T,
1997 return val();
1998 }
1999 template <class U = T,
2001 constexpr const U &&operator*() const && {
2003 return std::move(val());
2004 }
2005 template <class U = T,
2009 return std::move(val());
2010 }
2011
2012 constexpr bool has_value() const noexcept { return this->m_has_val; }
2013 constexpr explicit operator bool() const noexcept { return this->m_has_val; }
2014
2015 template <class U = T,
2017 TL_EXPECTED_11_CONSTEXPR const U &value() const & {
2018 if (!has_value())
2020 return val();
2021 }
2022 template <class U = T,
2025 if (!has_value())
2027 return val();
2028 }
2029 template <class U = T,
2031 TL_EXPECTED_11_CONSTEXPR const U &&value() const && {
2032 if (!has_value())
2034 return std::move(val());
2035 }
2036 template <class U = T,
2039 if (!has_value())
2041 return std::move(val());
2042 }
2043
2044 constexpr const E &error() const & {
2045 TL_ASSERT(!has_value());
2046 return err().value();
2047 }
2049 TL_ASSERT(!has_value());
2050 return err().value();
2051 }
2052 constexpr const E &&error() const && {
2053 TL_ASSERT(!has_value());
2054 return std::move(err().value());
2055 }
2057 TL_ASSERT(!has_value());
2058 return std::move(err().value());
2059 }
2060
2061 template <class U> constexpr T value_or(U &&v) const & {
2062 static_assert(std::is_copy_constructible<T>::value &&
2063 std::is_convertible<U &&, T>::value,
2064 "T must be copy-constructible and convertible to from U&&");
2065 return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));
2066 }
2067 template <class U> TL_EXPECTED_11_CONSTEXPR T value_or(U &&v) && {
2068 static_assert(std::is_move_constructible<T>::value &&
2069 std::is_convertible<U &&, T>::value,
2070 "T must be move-constructible and convertible to from U&&");
2071 return bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(v));
2072 }
2073};
2074
2075namespace detail {
2076template <class Exp> using exp_t = typename detail::decay_t<Exp>::value_type;
2077template <class Exp> using err_t = typename detail::decay_t<Exp>::error_type;
2078template <class Exp, class Ret> using ret_t = expected<Ret, err_t<Exp>>;
2079
2080#ifdef TL_EXPECTED_CXX14
2081template <class Exp, class F,
2083 class Ret = decltype(detail::invoke(std::declval<F>(),
2084 *std::declval<Exp>()))>
2085constexpr auto and_then_impl(Exp &&exp, F &&f) {
2086 static_assert(detail::is_expected<Ret>::value, "F must return an expected");
2087
2088 return exp.has_value()
2089 ? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
2090 : Ret(unexpect, std::forward<Exp>(exp).error());
2091}
2092
2093template <class Exp, class F,
2095 class Ret = decltype(detail::invoke(std::declval<F>()))>
2096constexpr auto and_then_impl(Exp &&exp, F &&f) {
2097 static_assert(detail::is_expected<Ret>::value, "F must return an expected");
2098
2099 return exp.has_value() ? detail::invoke(std::forward<F>(f))
2100 : Ret(unexpect, std::forward<Exp>(exp).error());
2101}
2102#else
2103template <class> struct TC;
2104template <class Exp, class F,
2105 class Ret = decltype(detail::invoke(std::declval<F>(),
2106 *std::declval<Exp>())),
2107 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr>
2108auto and_then_impl(Exp &&exp, F &&f) -> Ret {
2109 static_assert(detail::is_expected<Ret>::value, "F must return an expected");
2110
2111 return exp.has_value()
2112 ? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
2113 : Ret(unexpect, std::forward<Exp>(exp).error());
2114}
2115
2116template <class Exp, class F,
2117 class Ret = decltype(detail::invoke(std::declval<F>())),
2118 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr>
2119constexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret {
2120 static_assert(detail::is_expected<Ret>::value, "F must return an expected");
2121
2122 return exp.has_value() ? detail::invoke(std::forward<F>(f))
2123 : Ret(unexpect, std::forward<Exp>(exp).error());
2124}
2125#endif
2126
2127#ifdef TL_EXPECTED_CXX14
2128template <class Exp, class F,
2130 class Ret = decltype(detail::invoke(std::declval<F>(),
2131 *std::declval<Exp>())),
2132 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2133constexpr auto expected_map_impl(Exp &&exp, F &&f) {
2134 using result = ret_t<Exp, detail::decay_t<Ret>>;
2135 return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
2136 *std::forward<Exp>(exp)))
2137 : result(unexpect, std::forward<Exp>(exp).error());
2138}
2139
2140template <class Exp, class F,
2141 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2142 class Ret = decltype(detail::invoke(std::declval<F>(),
2143 *std::declval<Exp>())),
2144 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2145auto expected_map_impl(Exp &&exp, F &&f) {
2146 using result = expected<void, err_t<Exp>>;
2147 if (exp.has_value()) {
2148 detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
2149 return result();
2150 }
2151
2152 return result(unexpect, std::forward<Exp>(exp).error());
2153}
2154
2155template <class Exp, class F,
2156 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2157 class Ret = decltype(detail::invoke(std::declval<F>())),
2158 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2159constexpr auto expected_map_impl(Exp &&exp, F &&f) {
2160 using result = ret_t<Exp, detail::decay_t<Ret>>;
2161 return exp.has_value() ? result(detail::invoke(std::forward<F>(f)))
2162 : result(unexpect, std::forward<Exp>(exp).error());
2163}
2164
2165template <class Exp, class F,
2166 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2167 class Ret = decltype(detail::invoke(std::declval<F>())),
2168 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2169auto expected_map_impl(Exp &&exp, F &&f) {
2170 using result = expected<void, err_t<Exp>>;
2171 if (exp.has_value()) {
2172 detail::invoke(std::forward<F>(f));
2173 return result();
2174 }
2175
2176 return result(unexpect, std::forward<Exp>(exp).error());
2177}
2178#else
2179template <class Exp, class F,
2180 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2181 class Ret = decltype(detail::invoke(std::declval<F>(),
2182 *std::declval<Exp>())),
2183 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2184
2185constexpr auto expected_map_impl(Exp &&exp, F &&f)
2187 using result = ret_t<Exp, detail::decay_t<Ret>>;
2188
2189 return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
2190 *std::forward<Exp>(exp)))
2191 : result(unexpect, std::forward<Exp>(exp).error());
2192}
2193
2194template <class Exp, class F,
2196 class Ret = decltype(detail::invoke(std::declval<F>(),
2197 *std::declval<Exp>())),
2198 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2199
2201 if (exp.has_value()) {
2202 detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
2203 return {};
2204 }
2205
2206 return unexpected<err_t<Exp>>(std::forward<Exp>(exp).error());
2207}
2208
2209template <class Exp, class F,
2211 class Ret = decltype(detail::invoke(std::declval<F>())),
2212 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2213
2214constexpr auto expected_map_impl(Exp &&exp, F &&f)
2216 using result = ret_t<Exp, detail::decay_t<Ret>>;
2217
2218 return exp.has_value() ? result(detail::invoke(std::forward<F>(f)))
2219 : result(unexpect, std::forward<Exp>(exp).error());
2220}
2221
2222template <class Exp, class F,
2224 class Ret = decltype(detail::invoke(std::declval<F>())),
2225 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2226
2228 if (exp.has_value()) {
2229 detail::invoke(std::forward<F>(f));
2230 return {};
2231 }
2232
2233 return unexpected<err_t<Exp>>(std::forward<Exp>(exp).error());
2234}
2235#endif
2236
2237#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \
2238 !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)
2239template <class Exp, class F,
2241 class Ret = decltype(detail::invoke(std::declval<F>(),
2242 std::declval<Exp>().error())),
2243 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2244constexpr auto map_error_impl(Exp &&exp, F &&f) {
2246 return exp.has_value()
2247 ? result(*std::forward<Exp>(exp))
2248 : result(unexpect, detail::invoke(std::forward<F>(f),
2249 std::forward<Exp>(exp).error()));
2250}
2251template <class Exp, class F,
2252 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2253 class Ret = decltype(detail::invoke(std::declval<F>(),
2254 std::declval<Exp>().error())),
2255 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2256auto map_error_impl(Exp &&exp, F &&f) {
2257 using result = expected<exp_t<Exp>, monostate>;
2258 if (exp.has_value()) {
2259 return result(*std::forward<Exp>(exp));
2260 }
2261
2262 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2263 return result(unexpect, monostate{});
2264}
2265template <class Exp, class F,
2266 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2267 class Ret = decltype(detail::invoke(std::declval<F>(),
2268 std::declval<Exp>().error())),
2269 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2270constexpr auto map_error_impl(Exp &&exp, F &&f) {
2271 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2272 return exp.has_value()
2273 ? result()
2274 : result(unexpect, detail::invoke(std::forward<F>(f),
2275 std::forward<Exp>(exp).error()));
2276}
2277template <class Exp, class F,
2278 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2279 class Ret = decltype(detail::invoke(std::declval<F>(),
2280 std::declval<Exp>().error())),
2281 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2282auto map_error_impl(Exp &&exp, F &&f) {
2283 using result = expected<exp_t<Exp>, monostate>;
2284 if (exp.has_value()) {
2285 return result();
2286 }
2287
2288 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2289 return result(unexpect, monostate{});
2290}
2291#else
2292template <class Exp, class F,
2293 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2294 class Ret = decltype(detail::invoke(std::declval<F>(),
2295 std::declval<Exp>().error())),
2296 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2297constexpr auto map_error_impl(Exp &&exp, F &&f)
2300
2301 return exp.has_value()
2302 ? result(*std::forward<Exp>(exp))
2303 : result(unexpect, detail::invoke(std::forward<F>(f),
2304 std::forward<Exp>(exp).error()));
2305}
2306
2307template <class Exp, class F,
2309 class Ret = decltype(detail::invoke(std::declval<F>(),
2310 std::declval<Exp>().error())),
2311 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2312auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate> {
2313 using result = expected<exp_t<Exp>, monostate>;
2314 if (exp.has_value()) {
2315 return result(*std::forward<Exp>(exp));
2316 }
2317
2318 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2319 return result(unexpect, monostate{});
2320}
2321
2322template <class Exp, class F,
2324 class Ret = decltype(detail::invoke(std::declval<F>(),
2325 std::declval<Exp>().error())),
2326 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2327constexpr auto map_error_impl(Exp &&exp, F &&f)
2330
2331 return exp.has_value()
2332 ? result()
2333 : result(unexpect, detail::invoke(std::forward<F>(f),
2334 std::forward<Exp>(exp).error()));
2335}
2336
2337template <class Exp, class F,
2339 class Ret = decltype(detail::invoke(std::declval<F>(),
2340 std::declval<Exp>().error())),
2341 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2342auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate> {
2343 using result = expected<exp_t<Exp>, monostate>;
2344 if (exp.has_value()) {
2345 return result();
2346 }
2347
2348 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2349 return result(unexpect, monostate{});
2350}
2351#endif
2352
2353#ifdef TL_EXPECTED_CXX14
2354template <class Exp, class F,
2355 class Ret = decltype(detail::invoke(std::declval<F>(),
2356 std::declval<Exp>().error())),
2357 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2358constexpr auto or_else_impl(Exp &&exp, F &&f) {
2359 static_assert(detail::is_expected<Ret>::value, "F must return an expected");
2360 return exp.has_value() ? std::forward<Exp>(exp)
2361 : detail::invoke(std::forward<F>(f),
2362 std::forward<Exp>(exp).error());
2363}
2364
2365template <class Exp, class F,
2366 class Ret = decltype(detail::invoke(std::declval<F>(),
2367 std::declval<Exp>().error())),
2368 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2369detail::decay_t<Exp> or_else_impl(Exp &&exp, F &&f) {
2370 return exp.has_value() ? std::forward<Exp>(exp)
2371 : (detail::invoke(std::forward<F>(f),
2372 std::forward<Exp>(exp).error()),
2373 std::forward<Exp>(exp));
2374}
2375#else
2376template <class Exp, class F,
2377 class Ret = decltype(detail::invoke(std::declval<F>(),
2378 std::declval<Exp>().error())),
2379 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2380auto or_else_impl(Exp &&exp, F &&f) -> Ret {
2381 static_assert(detail::is_expected<Ret>::value, "F must return an expected");
2382 return exp.has_value() ? std::forward<Exp>(exp)
2383 : detail::invoke(std::forward<F>(f),
2384 std::forward<Exp>(exp).error());
2385}
2386
2387template <class Exp, class F,
2388 class Ret = decltype(detail::invoke(std::declval<F>(),
2389 std::declval<Exp>().error())),
2390 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2392 return exp.has_value() ? std::forward<Exp>(exp)
2393 : (detail::invoke(std::forward<F>(f),
2394 std::forward<Exp>(exp).error()),
2395 std::forward<Exp>(exp));
2396}
2397#endif
2398} // namespace detail
2399
2400template <class T, class E, class U, class F>
2401constexpr bool operator==(const expected<T, E> &lhs,
2402 const expected<U, F> &rhs) {
2403 return (lhs.has_value() != rhs.has_value())
2404 ? false
2405 : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs);
2406}
2407template <class T, class E, class U, class F>
2408constexpr bool operator!=(const expected<T, E> &lhs,
2409 const expected<U, F> &rhs) {
2410 return (lhs.has_value() != rhs.has_value())
2411 ? true
2412 : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs);
2413}
2414template <class E, class F>
2415constexpr bool operator==(const expected<void, E> &lhs,
2416 const expected<void, F> &rhs) {
2417 return (lhs.has_value() != rhs.has_value())
2418 ? false
2419 : (!lhs.has_value() ? lhs.error() == rhs.error() : true);
2420}
2421template <class E, class F>
2422constexpr bool operator!=(const expected<void, E> &lhs,
2423 const expected<void, F> &rhs) {
2424 return (lhs.has_value() != rhs.has_value())
2425 ? true
2426 : (!lhs.has_value() ? lhs.error() != rhs.error() : false);
2427}
2428
2429template <class T, class E, class U>
2430constexpr bool operator==(const expected<T, E> &x, const U &v) {
2431 return x.has_value() ? *x == v : false;
2432}
2433template <class T, class E, class U>
2434constexpr bool operator==(const U &v, const expected<T, E> &x) {
2435 return x.has_value() ? *x == v : false;
2436}
2437template <class T, class E, class U>
2438constexpr bool operator!=(const expected<T, E> &x, const U &v) {
2439 return x.has_value() ? *x != v : true;
2440}
2441template <class T, class E, class U>
2442constexpr bool operator!=(const U &v, const expected<T, E> &x) {
2443 return x.has_value() ? *x != v : true;
2444}
2445
2446template <class T, class E>
2447constexpr bool operator==(const expected<T, E> &x, const unexpected<E> &e) {
2448 return x.has_value() ? false : x.error() == e.value();
2449}
2450template <class T, class E>
2451constexpr bool operator==(const unexpected<E> &e, const expected<T, E> &x) {
2452 return x.has_value() ? false : x.error() == e.value();
2453}
2454template <class T, class E>
2455constexpr bool operator!=(const expected<T, E> &x, const unexpected<E> &e) {
2456 return x.has_value() ? true : x.error() != e.value();
2457}
2458template <class T, class E>
2459constexpr bool operator!=(const unexpected<E> &e, const expected<T, E> &x) {
2460 return x.has_value() ? true : x.error() != e.value();
2461}
2462
2463template <class T, class E,
2464 detail::enable_if_t<(std::is_void<T>::value ||
2465 std::is_move_constructible<T>::value) &&
2466 detail::is_swappable<T>::value &&
2467 std::is_move_constructible<E>::value &&
2468 detail::is_swappable<E>::value> * = nullptr>
2470 expected<T, E> &rhs) noexcept(noexcept(lhs.swap(rhs))) {
2471 lhs.swap(rhs);
2472}
2473} // namespace tl
2474
2475#endif
Definition expected.hpp:1252
bad_expected_access(E e)
Definition expected.hpp:1254
E & error() &
Definition expected.hpp:1261
virtual const char * what() const noexcept override
Definition expected.hpp:1256
const E & error() const &
Definition expected.hpp:1260
E && error() &&
Definition expected.hpp:1263
const E && error() const &&
Definition expected.hpp:1262
An expected<T, E> object is an object that contains the storage for another object and manages the li...
Definition expected.hpp:1281
constexpr T * operator->()
Definition expected.hpp:1982
constexpr U & operator*() &
Definition expected.hpp:1995
constexpr T value_or(U &&v) &&
Definition expected.hpp:2067
constexpr expected(const unexpected< G > &e)
Definition expected.hpp:1583
expected & operator=(const expected &rhs)=default
constexpr T value_or(U &&v) const &
Definition expected.hpp:2061
constexpr decltype(map_error_impl(std::declval< expected & >(), std::declval< F && >())) transform_error(F &&f) &
Definition expected.hpp:1516
constexpr decltype(map_error_impl(std::declval< const expected && >(), std::declval< F && >())) transform_error(F &&f) const &&
Definition expected.hpp:1536
constexpr auto and_then(F &&f) const &&-> decltype(and_then_impl(std::declval< expected const && >(), std::forward< F >(f)))
Definition expected.hpp:1360
constexpr const E && error() const &&
Definition expected.hpp:2052
constexpr U && operator*() &&
Definition expected.hpp:2007
constexpr decltype(expected_map_impl(std::declval< const expected && >(), std::declval< F && >())) transform(F &&f) const &&
Definition expected.hpp:1449
constexpr expected(expected< U, G > &&rhs)
Definition expected.hpp:1664
void emplace(std::initializer_list< U > il, Args &&...args)
Definition expected.hpp:1831
constexpr expected(const expected &rhs)=default
constexpr decltype(expected_map_impl(std::declval< expected >(), std::declval< F && >())) map(F &&f) &&
Definition expected.hpp:1391
constexpr decltype(expected_map_impl(std::declval< expected & >(), std::declval< F && >())) map(F &&f) &
Definition expected.hpp:1385
constexpr decltype(expected_map_impl(std::declval< expected >(), std::declval< F && >())) transform(F &&f) &&
Definition expected.hpp:1435
constexpr const E & error() const &
Definition expected.hpp:2044
constexpr const U && value() const &&
Definition expected.hpp:2031
constexpr bool has_value() const noexcept
Definition expected.hpp:2012
constexpr expected()=default
constexpr auto and_then(F &&f) const &-> decltype(and_then_impl(std::declval< expected const & >(), std::forward< F >(f)))
Definition expected.hpp:1353
constexpr expected(unexpected< G > &&e) noexcept(std::is_nothrow_constructible< E, G && >::value)
Definition expected.hpp:1600
constexpr expected(unexpect_t, Args &&...args)
Definition expected.hpp:1617
constexpr decltype(map_error_impl(std::declval< expected && >(), std::declval< F && >())) map_error(F &&f) &&
Definition expected.hpp:1479
constexpr const T * operator->() const
Definition expected.hpp:1978
constexpr decltype(expected_map_impl(std::declval< expected & >(), std::declval< F && >())) transform(F &&f) &
Definition expected.hpp:1429
constexpr decltype(expected_map_impl(std::declval< const expected & >(), std::declval< F && >())) transform(F &&f) const &
Definition expected.hpp:1441
constexpr const U & value() const &
Definition expected.hpp:2017
constexpr E & error() &
Definition expected.hpp:2048
constexpr expected(unexpected< G > const &e)
Definition expected.hpp:1592
constexpr expected(U &&v)
Definition expected.hpp:1691
expected & operator=(const unexpected< G > &rhs)
Definition expected.hpp:1764
constexpr auto and_then(F &&f) &&-> decltype(and_then_impl(std::declval< expected && >(), std::forward< F >(f)))
Definition expected.hpp:1348
detail::enable_if_t< detail::is_swappable< OT >::value &&detail::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::is_nothrow_swappable< T >::value &&std::is_nothrow_move_constructible< E >::value &&detail::is_nothrow_swappable< E >::value)
Definition expected.hpp:1961
void emplace(Args &&...args)
Definition expected.hpp:1793
constexpr auto and_then(F &&f) &-> decltype(and_then_impl(std::declval< expected & >(), std::forward< F >(f)))
Definition expected.hpp:1342
constexpr decltype(map_error_impl(std::declval< expected && >(), std::declval< F && >())) transform_error(F &&f) &&
Definition expected.hpp:1522
expected & operator=(U &&v)
Definition expected.hpp:1713
constexpr expected(unexpect_t, std::initializer_list< U > il, Args &&...args)
Definition expected.hpp:1624
constexpr expected(const expected< U, G > &rhs)
Definition expected.hpp:1635
constexpr decltype(map_error_impl(std::declval< const expected & >(), std::declval< F && >())) map_error(F &&f) const &
Definition expected.hpp:1485
expected constexpr or_else(F &&f) const &
Definition expected.hpp:1549
T value_type
Definition expected.hpp:1317
constexpr expected(in_place_t, std::initializer_list< U > il, Args &&...args)
Definition expected.hpp:1574
expected constexpr or_else(F &&f) &
Definition expected.hpp:1541
constexpr expected(expected &&rhs)=default
expected constexpr or_else(F &&f) &&
Definition expected.hpp:1545
constexpr decltype(map_error_impl(std::declval< expected & >(), std::declval< F && >())) map_error(F &&f) &
Definition expected.hpp:1473
constexpr decltype(map_error_impl(std::declval< const expected && >(), std::declval< F && >())) map_error(F &&f) const &&
Definition expected.hpp:1493
E error_type
Definition expected.hpp:1318
constexpr const U & operator*() const &
Definition expected.hpp:1989
constexpr expected(in_place_t, Args &&...args)
Definition expected.hpp:1567
constexpr U & value() &
Definition expected.hpp:2024
unexpected< E > unexpected_type
Definition expected.hpp:1319
expected & operator=(expected &&rhs)=default
expected constexpr or_else(F &&f) const &&
Definition expected.hpp:1554
expected & operator=(unexpected< G > &&rhs) noexcept
Definition expected.hpp:1779
constexpr const U && operator*() const &&
Definition expected.hpp:2001
constexpr decltype(map_error_impl(std::declval< const expected & >(), std::declval< F && >())) transform_error(F &&f) const &
Definition expected.hpp:1528
constexpr U && value() &&
Definition expected.hpp:2038
constexpr E && error() &&
Definition expected.hpp:2056
constexpr decltype(expected_map_impl(std::declval< const expected & >(), std::declval< F && >())) map(F &&f) const &
Definition expected.hpp:1397
constexpr decltype(expected_map_impl(std::declval< const expected && >(), std::declval< F && >())) map(F &&f) const &&
Definition expected.hpp:1405
Definition expected.hpp:146
Definition expected.hpp:154
constexpr unexpected(const E &e)
Definition expected.hpp:159
constexpr unexpected(Args &&...args)
Definition expected.hpp:165
constexpr E && value() &&
Definition expected.hpp:176
constexpr const E & value() const &
Definition expected.hpp:174
constexpr unexpected(std::initializer_list< U > l, Args &&...args)
Definition expected.hpp:171
constexpr E & value() &
Definition expected.hpp:175
constexpr const E && value() const &&
Definition expected.hpp:177
constexpr unexpected(E &&e)
Definition expected.hpp:161
unexpected()=delete
#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)
Definition expected.hpp:114
#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)
Definition expected.hpp:110
#define TL_EXPECTED_NODISCARD
Definition expected.hpp:138
#define TL_EXPECTED_MSVC2015_CONSTEXPR
Definition expected.hpp:36
#define TL_ASSERT(x)
Definition expected.hpp:66
#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T)
Definition expected.hpp:112
#define TL_EXPECTED_THROW_EXCEPTION(e)
Definition expected.hpp:225
#define TL_EXPECTED_11_CONSTEXPR
Definition expected.hpp:132
@ E
Definition AcceleratorCodes.hpp:82
@ U
Definition AcceleratorCodes.hpp:98
@ F
Definition AcceleratorCodes.hpp:83
@ T
Definition AcceleratorCodes.hpp:97
Definition string.h:155
Definition expected.hpp:330
std::false_type uses_std(...)
std::false_type can_swap(...) noexcept(false)
Definition expected.hpp:228
typename std::remove_reference< T >::type remove_reference_t
Definition expected.hpp:234
invoke_result_impl< F, void, Us... > invoke_result
Definition expected.hpp:318
is_void_or< T, std::is_move_assignable< T > > is_move_assignable_or_void
Definition expected.hpp:436
typename std::enable_if< E, T >::type enable_if_t
Definition expected.hpp:237
is_void_or< T, std::is_copy_assignable< T > > is_copy_assignable_or_void
Definition expected.hpp:433
typename std::decay< T >::type decay_t
Definition expected.hpp:235
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.hpp:291
typename detail::decay_t< Exp >::error_type err_t
Definition expected.hpp:2077
conditional_t< std::is_void< T >::value, std::true_type, U > is_void_or
Definition expected.hpp:422
detail::enable_if_t< std::is_constructible< T, U && >::value && !std::is_same< detail::decay_t< U >, in_place_t >::value && !std::is_same< expected< T, E >, detail::decay_t< U > >::value && !std::is_same< unexpected< E >, detail::decay_t< U > >::value > expected_enable_forward_value
Definition expected.hpp:402
typename std::remove_const< T >::type remove_const_t
Definition expected.hpp:232
constexpr auto map_error_impl(Exp &&exp, F &&f) -> expected< exp_t< Exp >, detail::decay_t< Ret > >
Definition expected.hpp:2297
auto and_then_impl(Exp &&exp, F &&f) -> Ret
Definition expected.hpp:2108
is_expected_impl< decay_t< T > > is_expected
Definition expected.hpp:399
typename std::conditional< B, T, F >::type conditional_t
Definition expected.hpp:239
is_void_or< T, std::is_copy_constructible< T > > is_copy_constructible_or_void
Definition expected.hpp:425
expected< Ret, err_t< Exp > > ret_t
Definition expected.hpp:2078
typename invoke_result< F, Us... >::type invoke_result_t
Definition expected.hpp:321
auto or_else_impl(Exp &&exp, F &&f) -> Ret
Definition expected.hpp:2380
detail::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.hpp:409
constexpr auto expected_map_impl(Exp &&exp, F &&f) -> ret_t< Exp, detail::decay_t< Ret > >
Definition expected.hpp:2185
is_void_or< T, std::is_move_constructible< T > > is_move_constructible_or_void
Definition expected.hpp:429
typename detail::decay_t< Exp >::value_type exp_t
Definition expected.hpp:2076
Definition expected.hpp:141
constexpr bool operator>=(const unexpected< E > &lhs, const unexpected< E > &rhs)
Definition expected.hpp:208
constexpr bool operator>(const unexpected< E > &lhs, const unexpected< E > &rhs)
Definition expected.hpp:204
constexpr bool operator!=(const unexpected< E > &lhs, const unexpected< E > &rhs)
Definition expected.hpp:192
constexpr bool operator==(const unexpected< E > &lhs, const unexpected< E > &rhs)
Definition expected.hpp:188
constexpr bool operator<=(const unexpected< E > &lhs, const unexpected< E > &rhs)
Definition expected.hpp:200
constexpr bool operator<(const unexpected< E > &lhs, const unexpected< E > &rhs)
Definition expected.hpp:196
unexpected< typename std::decay< E >::type > make_unexpected(E &&e)
Definition expected.hpp:213
void swap(expected< T, E > &lhs, expected< T, E > &rhs) noexcept(noexcept(lhs.swap(rhs)))
Definition expected.hpp:2469
Definition expected.hpp:2103
Definition expected.hpp:242
Definition expected.hpp:1212
constexpr default_constructor_tag()=default
expected_copy_assign_base & operator=(expected_copy_assign_base &&rhs)=default
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=(const expected_copy_assign_base &rhs)
Definition expected.hpp:1050
Definition expected.hpp:1038
expected_copy_base(expected_copy_base &&rhs)=default
expected_copy_base & operator=(const expected_copy_base &rhs)=default
expected_copy_base(const expected_copy_base &rhs)
Definition expected.hpp:976
expected_copy_base & operator=(expected_copy_base &&rhs)=default
Definition expected.hpp:966
constexpr expected_default_ctor_base() noexcept=delete
Definition expected.hpp:1222
constexpr expected_default_ctor_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_assign_base(expected_delete_assign_base &&) noexcept=default
expected_delete_assign_base(const expected_delete_assign_base &)=default
expected_delete_assign_base(const expected_delete_assign_base &)=default
expected_delete_assign_base(expected_delete_assign_base &&) noexcept=default
Definition expected.hpp:1163
expected_delete_assign_base(const expected_delete_assign_base &)=default
expected_delete_assign_base(expected_delete_assign_base &&) noexcept=default
expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept=delete
expected_delete_ctor_base(const expected_delete_ctor_base &)=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
Definition expected.hpp:1108
expected_delete_ctor_base(const expected_delete_ctor_base &)=default
expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept=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.hpp:1093
expected_move_assign_base(expected_move_assign_base &&rhs)=default
expected_move_assign_base(const expected_move_assign_base &rhs)=default
expected_move_assign_base & operator=(const expected_move_assign_base &rhs)=default
Definition expected.hpp:1072
expected_move_base & operator=(expected_move_base &&rhs)=default
expected_move_base & operator=(const expected_move_base &rhs)=default
expected_move_base(const expected_move_base &rhs)=default
expected_move_base(expected_move_base &&rhs) noexcept(std::is_nothrow_move_constructible< T >::value)
Definition expected.hpp:1012
Definition expected.hpp:999
void construct() noexcept
Definition expected.hpp:910
constexpr const unexpected< E > && geterr() const &&
Definition expected.hpp:949
constexpr const unexpected< E > & geterr() const &
Definition expected.hpp:944
void assign(Rhs &&rhs) noexcept
Definition expected.hpp:924
void construct_error(Args &&...args) noexcept
Definition expected.hpp:918
void construct_with(Rhs &&) noexcept
Definition expected.hpp:914
bool has_value() const
Definition expected.hpp:939
constexpr unexpected< E > && geterr() &&
Definition expected.hpp:945
constexpr void destroy_val()
Definition expected.hpp:954
constexpr unexpected< E > & geterr() &
Definition expected.hpp:941
Definition expected.hpp:721
constexpr const T && get() const &&
Definition expected.hpp:885
constexpr void destroy_val()
Definition expected.hpp:901
constexpr unexpected< E > && geterr() &&
Definition expected.hpp:892
constexpr const unexpected< E > & geterr() const &
Definition expected.hpp:891
constexpr const T & get() const &
Definition expected.hpp:882
constexpr unexpected< E > & geterr() &
Definition expected.hpp:888
constexpr const unexpected< E > && geterr() const &&
Definition expected.hpp:896
void construct(Args &&...args) noexcept
Definition expected.hpp:724
void assign(const expected_operations_base &rhs) noexcept
Definition expected.hpp:843
constexpr T & get() &
Definition expected.hpp:881
void construct_with(Rhs &&rhs) noexcept
Definition expected.hpp:729
void construct_error(Args &&...args) noexcept
Definition expected.hpp:734
void assign_common(Rhs &&rhs)
Definition expected.hpp:864
constexpr T && get() &&
Definition expected.hpp:883
void assign(expected_operations_base &&rhs) noexcept
Definition expected.hpp:852
bool has_value() const
Definition expected.hpp:879
expected_storage_base & operator=(expected_storage_base &&)=default
expected_storage_base & operator=(const expected_storage_base &)=default
expected_storage_base(expected_storage_base &&)=default
constexpr expected_storage_base(in_place_t, std::initializer_list< U > il, Args &&...args)
Definition expected.hpp:606
constexpr expected_storage_base(no_init_t)
Definition expected.hpp:595
expected_storage_base(const expected_storage_base &)=default
constexpr expected_storage_base(in_place_t, Args &&...args)
Definition expected.hpp:600
constexpr expected_storage_base()
Definition expected.hpp:594
constexpr expected_storage_base(unexpect_t, Args &&...args)
Definition expected.hpp:612
constexpr expected_storage_base(unexpect_t, std::initializer_list< U > il, Args &&...args)
Definition expected.hpp:618
unexpected< E > m_unexpect
Definition expected.hpp:634
constexpr expected_storage_base()
Definition expected.hpp:544
expected_storage_base & operator=(const expected_storage_base &)=default
constexpr expected_storage_base(unexpect_t, std::initializer_list< U > il, Args &&...args)
Definition expected.hpp:569
constexpr expected_storage_base(unexpect_t, Args &&...args)
Definition expected.hpp:563
expected_storage_base & operator=(expected_storage_base &&)=default
unexpected< E > m_unexpect
Definition expected.hpp:586
expected_storage_base(expected_storage_base &&)=default
constexpr expected_storage_base(no_init_t)
Definition expected.hpp:545
constexpr expected_storage_base(in_place_t, Args &&...args)
Definition expected.hpp:551
constexpr expected_storage_base(in_place_t, std::initializer_list< U > il, Args &&...args)
Definition expected.hpp:557
expected_storage_base(const expected_storage_base &)=default
constexpr expected_storage_base()
Definition expected.hpp:500
constexpr expected_storage_base(no_init_t)
Definition expected.hpp:501
expected_storage_base & operator=(const expected_storage_base &)=default
constexpr expected_storage_base(in_place_t, Args &&...args)
Definition expected.hpp:506
constexpr expected_storage_base(in_place_t, std::initializer_list< U > il, Args &&...args)
Definition expected.hpp:512
constexpr expected_storage_base(unexpect_t, Args &&...args)
Definition expected.hpp:518
expected_storage_base & operator=(expected_storage_base &&)=default
expected_storage_base(expected_storage_base &&)=default
constexpr expected_storage_base(unexpect_t, std::initializer_list< U > il, Args &&...args)
Definition expected.hpp:524
expected_storage_base(const expected_storage_base &)=default
unexpected< E > m_unexpect
Definition expected.hpp:536
constexpr expected_storage_base(in_place_t)
Definition expected.hpp:685
constexpr expected_storage_base()
Definition expected.hpp:682
constexpr expected_storage_base(unexpect_t, std::initializer_list< U > il, Args &&...args)
Definition expected.hpp:696
expected_storage_base(expected_storage_base &&)=default
unexpected< E > m_unexpect
Definition expected.hpp:712
constexpr expected_storage_base(unexpect_t, Args &&...args)
Definition expected.hpp:690
expected_storage_base(const expected_storage_base &)=default
expected_storage_base & operator=(const expected_storage_base &)=default
constexpr expected_storage_base(no_init_t)
Definition expected.hpp:683
expected_storage_base & operator=(expected_storage_base &&)=default
constexpr expected_storage_base(in_place_t)
Definition expected.hpp:651
expected_storage_base(expected_storage_base &&)=default
constexpr expected_storage_base(no_init_t)
Definition expected.hpp:649
constexpr expected_storage_base(unexpect_t, Args &&...args)
Definition expected.hpp:656
expected_storage_base(const expected_storage_base &)=default
expected_storage_base & operator=(expected_storage_base &&)=default
constexpr expected_storage_base(unexpect_t, std::initializer_list< U > il, Args &&...args)
Definition expected.hpp:662
expected_storage_base & operator=(const expected_storage_base &)=default
unexpected< E > m_unexpect
Definition expected.hpp:674
T m_val
Definition expected.hpp:490
constexpr expected_storage_base(unexpect_t, Args &&...args)
Definition expected.hpp:471
constexpr expected_storage_base(no_init_t)
Definition expected.hpp:454
bool m_has_val
Definition expected.hpp:494
~expected_storage_base()
Definition expected.hpp:482
constexpr expected_storage_base()
Definition expected.hpp:453
constexpr expected_storage_base(in_place_t, std::initializer_list< U > il, Args &&...args)
Definition expected.hpp:465
char m_no_init
Definition expected.hpp:492
constexpr expected_storage_base(in_place_t, Args &&...args)
Definition expected.hpp:459
unexpected< E > m_unexpect
Definition expected.hpp:491
constexpr expected_storage_base(unexpect_t, std::initializer_list< U > il, Args &&...args)
Definition expected.hpp:477
decltype(detail::invoke(std::declval< F >(), std::declval< Us >()...)) type
Definition expected.hpp:313
Definition expected.hpp:306
Definition expected.hpp:396
Definition expected.hpp:391
Definition expected.hpp:372
Definition expected.hpp:441
Definition expected.hpp:333
Definition expected.hpp:148
in_place_t()=default
Definition expected.hpp:217
unexpect_t()=default