Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qexpected_p.h
Go to the documentation of this file.
1// Copyright (C) 2017 Sy Brand (tartanllama@gmail.com, @TartanLlama)
2// SPDX-License-Identifier: CC0-1.0
3
4///
5// expected - An implementation of std::expected with extensions
6// Written in 2017 by Sy Brand (tartanllama@gmail.com, @TartanLlama)
7//
8// Documentation available at http://tl.tartanllama.xyz/
9//
10// To the extent possible under law, the author(s) have dedicated all
11// copyright and related and neighboring rights to this software to the
12// public domain worldwide. This software is distributed without any warranty.
13//
14// You should have received a copy of the CC0 Public Domain Dedication
15// along with this software. If not, see
16// <http://creativecommons.org/publicdomain/zero/1.0/>.
17///
18
19#ifndef TL_EXPECTED_HPP
20#define TL_EXPECTED_HPP
21
22//
23// W A R N I N G
24// -------------
25//
26// This file is not part of the Qt API. It exists purely as an
27// implementation detail. This header file may change from version to
28// version without notice, or even be removed.
29//
30// We mean it.
31//
32
33#define TL_EXPECTED_VERSION_MAJOR 1
34#define TL_EXPECTED_VERSION_MINOR 1
35#define TL_EXPECTED_VERSION_PATCH 0
36
37#include <QtCore/private/qglobal_p.h>
38#include <QtCore/qassert.h>
39#include <QtCore/qtconfiginclude.h>
40#include <QtCore/qtconfigmacros.h>
41
42#include <exception>
43#include <functional>
44#include <type_traits>
45#include <utility>
46
47#define TL_ASSERT Q_ASSERT
48
49#if defined(__EXCEPTIONS) || defined(_CPPUNWIND)
50#define TL_EXPECTED_EXCEPTIONS_ENABLED
51#endif
52
53#if defined(TL_EXPECTED_EXCEPTIONS_ENABLED) && defined(QT_NO_EXCEPTIONS)
54# undef TL_EXPECTED_EXCEPTIONS_ENABLED
55#endif
56
57#if (defined(_MSC_VER) && _MSC_VER == 1900)
58#define TL_EXPECTED_MSVC2015
59#define TL_EXPECTED_MSVC2015_CONSTEXPR
60#else
61#define TL_EXPECTED_MSVC2015_CONSTEXPR constexpr
62#endif
63
64#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 &&
65 !defined(__clang__))
66#define TL_EXPECTED_GCC49
67#endif
68
69#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 &&
70 !defined(__clang__))
71#define TL_EXPECTED_GCC54
72#endif
73
74#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 &&
75 !defined(__clang__))
76#define TL_EXPECTED_GCC55
77#endif
78
79#if !defined(TL_ASSERT)
80//can't have assert in constexpr in C++11 and GCC 4.9 has a compiler bug
81#if (TL_CPLUSPLUS > 201103L) && !defined(TL_EXPECTED_GCC49)
82#include <cassert>
83#define TL_ASSERT(x) assert(x)
84#else
85#define TL_ASSERT(x)
86#endif
87#endif
88
89#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 &&
90 !defined(__clang__))
91// GCC < 5 doesn't support overloading on const&& for member functions
92
93#define TL_EXPECTED_NO_CONSTRR
94// GCC < 5 doesn't support some standard C++11 type traits
95#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)
96 std::has_trivial_copy_constructor<T>
97#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T)
98 std::has_trivial_copy_assign<T>
99
100// This one will be different for GCC 5.7 if it's ever supported
101#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)
102 std::is_trivially_destructible<T>
103
104// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks
105// std::vector for non-copyable types
106#elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__))
107#ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
108#define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
109QT_BEGIN_NAMESPACE
110namespace q23 {
111namespace detail {
112template <class T>
113struct is_trivially_copy_constructible
114 : std::is_trivially_copy_constructible<T> {};
115#ifdef _GLIBCXX_VECTOR
116template <class T, class A>
117struct is_trivially_copy_constructible<std::vector<T, A>> : std::false_type {};
118#endif
119} // namespace detail
120} // namespace q23
121QT_END_NAMESPACE
122#endif
123
124#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)
125 q23::detail::is_trivially_copy_constructible<T>
126#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T)
127 std::is_trivially_copy_assignable<T>
128#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)
129 std::is_trivially_destructible<T>
130#else
131#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)
132 std::is_trivially_copy_constructible<T>
133#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T)
134 std::is_trivially_copy_assignable<T>
135#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)
136 std::is_trivially_destructible<T>
137#endif
138
139#ifdef _MSVC_LANG
140#define TL_CPLUSPLUS _MSVC_LANG
141#else
142#define TL_CPLUSPLUS __cplusplus
143#endif
144
145#if TL_CPLUSPLUS > 201103L
146#define TL_EXPECTED_CXX14
147#endif
148
149#ifdef TL_EXPECTED_GCC49
150#define TL_EXPECTED_GCC49_CONSTEXPR
151#else
152#define TL_EXPECTED_GCC49_CONSTEXPR constexpr
153#endif
154
155#if (TL_CPLUSPLUS == 201103L || defined(TL_EXPECTED_MSVC2015) ||
156 defined(TL_EXPECTED_GCC49))
157#define TL_EXPECTED_11_CONSTEXPR
158#else
159#define TL_EXPECTED_11_CONSTEXPR constexpr
160#endif
161
162QT_BEGIN_NAMESPACE
163namespace q23 {
164template <class T, class E> class expected;
165
166#ifndef TL_MONOSTATE_INPLACE_MUTEX
167#define TL_MONOSTATE_INPLACE_MUTEX
168class monostate {};
169
171 explicit in_place_t() = default;
172};
173static constexpr in_place_t in_place{};
174#endif
175
176template <class E> class unexpected {
177public:
178 static_assert(!std::is_same<E, void>::value, "E must not be void");
179
180 unexpected() = delete;
181 constexpr explicit unexpected(const E &e) : m_val(e) {}
182
183 constexpr explicit unexpected(E &&e) : m_val(std::move(e)) {}
184
185 template <class... Args, typename std::enable_if<std::is_constructible<
186 E, Args &&...>::value>::type * = nullptr>
187 constexpr explicit unexpected(in_place_t, Args &&...args)
188 : m_val(std::forward<Args>(args)...) {}
189
190 template <
191 class U, class... Args,
192 typename std::enable_if<std::is_constructible<
193 E, std::initializer_list<U> &, Args &&...>::value>::type * = nullptr>
194 constexpr explicit unexpected(in_place_t, std::initializer_list<U> l,
195 Args &&...args)
196 : m_val(l, std::forward<Args>(args)...) {}
197
198 constexpr const E &error() const & { return m_val; }
199 TL_EXPECTED_11_CONSTEXPR E &error() & { return m_val; }
200 TL_EXPECTED_11_CONSTEXPR E &&error() && { return std::move(m_val); }
201 constexpr const E &&error() const && { return std::move(m_val); }
202
203private:
204 E m_val;
205};
206
207#ifdef __cpp_deduction_guides
208template <class E> unexpected(E) -> unexpected<E>;
209#endif
210
211template <class E>
212constexpr bool operator==(const unexpected<E> &lhs, const unexpected<E> &rhs) {
213 return lhs.error() == rhs.error();
214}
215template <class E>
216constexpr bool operator!=(const unexpected<E> &lhs, const unexpected<E> &rhs) {
217 return lhs.error() != rhs.error();
218}
219template <class E>
220constexpr bool operator<(const unexpected<E> &lhs, const unexpected<E> &rhs) {
221 return lhs.error() < rhs.error();
222}
223template <class E>
224constexpr bool operator<=(const unexpected<E> &lhs, const unexpected<E> &rhs) {
225 return lhs.error() <= rhs.error();
226}
227template <class E>
228constexpr bool operator>(const unexpected<E> &lhs, const unexpected<E> &rhs) {
229 return lhs.error() > rhs.error();
230}
231template <class E>
232constexpr bool operator>=(const unexpected<E> &lhs, const unexpected<E> &rhs) {
233 return lhs.error() >= rhs.error();
234}
235
236template <class E>
237unexpected<typename std::decay<E>::type> make_unexpected(E &&e) {
238 return unexpected<typename std::decay<E>::type>(std::forward<E>(e));
239}
240
242 unexpect_t() = default;
243};
244static constexpr unexpect_t unexpect{};
245
246namespace detail {
247template <typename E>
249#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
250 throw std::forward<E>(e);
251#else
252 (void)e;
253#ifdef _MSC_VER
254 __assume(0);
255#else
256 Q_UNREACHABLE();
257#endif
258#endif
259}
260
261#ifndef TL_TRAITS_MUTEX
262#define TL_TRAITS_MUTEX
263// C++14-style aliases for brevity
264template <class T> using remove_const_t = typename std::remove_const<T>::type;
265template <class T>
266using remove_reference_t = typename std::remove_reference<T>::type;
267template <class T> using decay_t = typename std::decay<T>::type;
268template <bool E, class T = void>
269using enable_if_t = typename std::enable_if<E, T>::type;
270template <bool B, class T, class F>
271using conditional_t = typename std::conditional<B, T, F>::type;
272
273// std::conjunction from C++17
274template <class...> struct conjunction : std::true_type {};
275template <class B> struct conjunction<B> : B {};
276template <class B, class... Bs>
277struct conjunction<B, Bs...>
278 : std::conditional<bool(B::value), conjunction<Bs...>, B>::type {};
279
280#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L
281#define TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
282#endif
283
284// In C++11 mode, there's an issue in libc++'s std::mem_fn
285// which results in a hard-error when using it in a noexcept expression
286// in some cases. This is a check to workaround the common failing case.
287#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
288template <class T>
290template <class T, class Ret, class... Args>
292 : std::true_type {};
293template <class T, class Ret, class... Args>
295 : std::true_type {};
296template <class T, class Ret, class... Args>
298 : std::true_type {};
299template <class T, class Ret, class... Args>
300struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile>
301 : std::true_type {};
302template <class T, class Ret, class... Args>
303struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile &>
304 : std::true_type {};
305template <class T, class Ret, class... Args>
306struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile &&>
307 : std::true_type {};
308
309template <class T> struct is_const_or_const_ref : std::false_type {};
310template <class T> struct is_const_or_const_ref<T const &> : std::true_type {};
311template <class T> struct is_const_or_const_ref<T const> : std::true_type {};
312#endif
313
314// std::invoke from C++17
315// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround
316template <
317 typename Fn, typename... Args,
318#ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
321#endif
322 typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>, int = 0>
323constexpr auto invoke(Fn &&f, Args &&...args) noexcept(
324 noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))
325 -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) {
326 return std::mem_fn(f)(std::forward<Args>(args)...);
327}
328
329template <typename Fn, typename... Args,
331constexpr auto invoke(Fn &&f, Args &&...args) noexcept(
332 noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))
333 -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) {
334 return std::forward<Fn>(f)(std::forward<Args>(args)...);
335}
336
337// std::invoke_result from C++17
338template <class F, class, class... Us> struct invoke_result_impl;
339
340template <class F, class... Us>
342 F,
343 decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...), void()),
344 Us...> {
345 using type =
346 decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...));
347};
348
349template <class F, class... Us>
350using invoke_result = invoke_result_impl<F, void, Us...>;
351
352template <class F, class... Us>
353using invoke_result_t = typename invoke_result<F, Us...>::type;
354
355#if defined(_MSC_VER) && _MSC_VER <= 1900
356// TODO make a version which works with MSVC 2015
357template <class T, class U = T> struct is_swappable : std::true_type {};
358
359template <class T, class U = T> struct is_nothrow_swappable : std::true_type {};
360#else
361// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept
362namespace swap_adl_tests {
363// if swap ADL finds this then it would call std::swap otherwise (same
364// signature)
365struct tag {};
366
367template <class T> tag swap(T &, T &);
368template <class T, std::size_t N> tag swap(T (&a)[N], T (&b)[N]);
369
370// helper functions to test if an unqualified swap is possible, and if it
371// becomes std::swap
372template <class, class> std::false_type can_swap(...) noexcept(false);
373template <class T, class U,
374 class = decltype(swap(std::declval<T &>(), std::declval<U &>()))>
375std::true_type can_swap(int) noexcept(noexcept(swap(std::declval<T &>(),
376 std::declval<U &>())));
377
378template <class, class> std::false_type uses_std(...);
379template <class T, class U>
380std::is_same<decltype(swap(std::declval<T &>(), std::declval<U &>())), tag>
382
383template <class T>
388
389template <class T, std::size_t N>
391
392template <class T, class U>
394 : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};
395} // namespace swap_adl_tests
396
397template <class T, class U = T>
400 bool,
401 decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&
402 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||
405
406template <class T, std::size_t N>
407struct is_swappable<T[N], T[N]>
409 bool,
410 decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&
411 (!decltype(detail::swap_adl_tests::uses_std<T[N], T[N]>(
412 0))::value ||
413 is_swappable<T, T>::value)> {};
414
415template <class T, class U = T>
424#endif
425#endif
426
427// Trait for checking if a type is a q23::expected
428template <class T> struct is_expected_impl : std::false_type {};
429template <class T, class E>
431template <class T> using is_expected = is_expected_impl<decay_t<T>>;
432
433template <class T, class E, class U>
435 std::is_constructible<T, U &&>::value &&
439
440template <class T, class E, class U, class G, class UR, class GR>
445 !std::is_constructible<T, expected<U, G> &&>::value &&
446 !std::is_constructible<T, const expected<U, G> &>::value &&
447 !std::is_constructible<T, const expected<U, G> &&>::value &&
448 !std::is_convertible<expected<U, G> &, T>::value &&
449 !std::is_convertible<expected<U, G> &&, T>::value &&
450 !std::is_convertible<const expected<U, G> &, T>::value &&
451 !std::is_convertible<const expected<U, G> &&, T>::value>;
452
453template <class T, class U>
455
456template <class T>
459
460template <class T>
463
464template <class T>
466
467template <class T>
469
470} // namespace detail
471
472namespace detail {
473struct no_init_t {};
474static constexpr no_init_t no_init{};
475
476// Implements the storage of the values, and ensures that the destructor is
477// trivial if it can be.
478//
479// This specialization is for where neither `T` or `E` is trivially
480// destructible, so the destructors must be called on destruction of the
481// `expected`
482template <class T, class E, bool = std::is_trivially_destructible<T>::value,
483 bool = std::is_trivially_destructible<E>::value>
485 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
487
488 template <class... Args,
489 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
490 nullptr>
491 constexpr expected_storage_base(in_place_t, Args &&...args)
492 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
493
494 template <class U, class... Args,
495 detail::enable_if_t<std::is_constructible<
496 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
497 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
498 Args &&...args)
499 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
500 template <class... Args,
501 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
502 nullptr>
503 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
504 : m_unexpect(in_place, std::forward<Args>(args)...), m_has_val(false) {}
505
506 template <class U, class... Args,
507 detail::enable_if_t<std::is_constructible<
508 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
510 std::initializer_list<U> il,
511 Args &&...args)
512 : m_unexpect(in_place, il, std::forward<Args>(args)...), m_has_val(false) {}
513
515 if (m_has_val) {
516 m_val.~T();
517 } else {
518 m_unexpect.~unexpected<E>();
519 }
520 }
521 union {
525 };
527};
528
529// This specialization is for when both `T` and `E` are trivially-destructible,
530// so the destructor of the `expected` can be trivial.
531template <class T, class E> struct expected_storage_base<T, E, true, true> {
532 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
534
535 template <class... Args,
536 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
537 nullptr>
538 constexpr expected_storage_base(in_place_t, Args &&...args)
539 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
540
541 template <class U, class... Args,
542 detail::enable_if_t<std::is_constructible<
543 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
544 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
545 Args &&...args)
546 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
547 template <class... Args,
548 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
549 nullptr>
550 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
551 : m_unexpect(in_place, std::forward<Args>(args)...), m_has_val(false) {}
552
553 template <class U, class... Args,
554 detail::enable_if_t<std::is_constructible<
555 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
557 std::initializer_list<U> il,
558 Args &&...args)
559 : m_unexpect(in_place, il, std::forward<Args>(args)...), m_has_val(false) {}
560
566 union {
570 };
572};
573
574// T is trivial, E is not.
575template <class T, class E> struct expected_storage_base<T, E, true, false> {
576 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
579
580 template <class... Args,
581 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
582 nullptr>
583 constexpr expected_storage_base(in_place_t, Args &&...args)
584 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
585
586 template <class U, class... Args,
587 detail::enable_if_t<std::is_constructible<
588 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
589 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
590 Args &&...args)
591 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
592 template <class... Args,
593 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
594 nullptr>
595 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
596 : m_unexpect(in_place, std::forward<Args>(args)...), m_has_val(false) {}
597
598 template <class U, class... Args,
599 detail::enable_if_t<std::is_constructible<
600 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
602 std::initializer_list<U> il,
603 Args &&...args)
604 : m_unexpect(in_place, il, std::forward<Args>(args)...), m_has_val(false) {}
605
611 if (!m_has_val) {
612 m_unexpect.~unexpected<E>();
613 }
614 }
615
616 union {
620 };
622};
623
624// E is trivial, T is not.
625template <class T, class E> struct expected_storage_base<T, E, false, true> {
626 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
628
629 template <class... Args,
630 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
631 nullptr>
632 constexpr expected_storage_base(in_place_t, Args &&...args)
633 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
634
635 template <class U, class... Args,
636 detail::enable_if_t<std::is_constructible<
637 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
638 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
639 Args &&...args)
640 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
641 template <class... Args,
642 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
643 nullptr>
644 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
645 : m_unexpect(in_place, std::forward<Args>(args)...), m_has_val(false) {}
646
647 template <class U, class... Args,
648 detail::enable_if_t<std::is_constructible<
649 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
651 std::initializer_list<U> il,
652 Args &&...args)
653 : m_unexpect(in_place, il, std::forward<Args>(args)...),
654 m_has_val(false) {}
655
661 if (m_has_val) {
662 m_val.~T();
663 }
664 }
665 union {
669 };
671};
672
673// `T` is `void`, `E` is trivially-destructible
674template <class E> struct expected_storage_base<void, E, false, true> {
675 #if __GNUC__ <= 5
676 //no constexpr for GCC 4/5 bug
677 #else
679 #endif
681
683
685
686 template <class... Args,
687 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
688 nullptr>
689 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
690 : m_unexpect(in_place, std::forward<Args>(args)...), m_has_val(false) {}
691
692 template <class U, class... Args,
693 detail::enable_if_t<std::is_constructible<
694 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
696 std::initializer_list<U> il,
697 Args &&...args)
698 : m_unexpect(in_place, il, std::forward<Args>(args)...), m_has_val(false) {}
699
705 struct dummy {};
706 union {
709 };
711};
712
713// `T` is `void`, `E` is not trivially-destructible
714template <class E> struct expected_storage_base<void, E, false, false> {
715 constexpr expected_storage_base() : m_dummy(), m_has_val(true) {}
717
719
720 template <class... Args,
721 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
722 nullptr>
723 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
724 : m_unexpect(in_place, std::forward<Args>(args)...), m_has_val(false) {}
725
726 template <class U, class... Args,
727 detail::enable_if_t<std::is_constructible<
728 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
730 std::initializer_list<U> il,
731 Args &&...args)
732 : m_unexpect(in_place, il, std::forward<Args>(args)...), m_has_val(false) {}
733
739 if (!m_has_val) {
740 m_unexpect.~unexpected<E>();
741 }
742 }
743
744 union {
747 };
749};
750
751// This base class provides some handy member functions which can be used in
752// further derived classes
753template <class T, class E>
756
757 template <class... Args> void construct(Args &&...args) noexcept {
758 new (std::addressof(this->m_val)) T(std::forward<Args>(args)...);
759 this->m_has_val = true;
760 }
761
762 template <class Rhs> void construct_with(Rhs &&rhs) noexcept {
763 new (std::addressof(this->m_val)) T(std::forward<Rhs>(rhs).get());
764 this->m_has_val = true;
765 }
766
767 template <class... Args> void construct_error(Args &&...args) noexcept {
768 new (std::addressof(this->m_unexpect))
769 unexpected<E>(std::forward<Args>(args)...);
770 this->m_has_val = false;
771 }
772
773#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
774
775 // These assign overloads ensure that the most efficient assignment
776 // implementation is used while maintaining the strong exception guarantee.
777 // The problematic case is where rhs has a value, but *this does not.
778 //
779 // This overload handles the case where we can just copy-construct `T`
780 // directly into place without throwing.
781 template <class U = T,
782 detail::enable_if_t<std::is_nothrow_copy_constructible<U>::value>
783 * = nullptr>
784 void assign(const expected_operations_base &rhs) noexcept {
785 if (!this->m_has_val && rhs.m_has_val) {
786 geterr().~unexpected<E>();
787 construct(rhs.get());
788 } else {
789 assign_common(rhs);
790 }
791 }
792
793 // This overload handles the case where we can attempt to create a copy of
794 // `T`, then no-throw move it into place if the copy was successful.
795 template <class U = T,
796 detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
797 std::is_nothrow_move_constructible<U>::value>
798 * = nullptr>
799 void assign(const expected_operations_base &rhs) noexcept {
800 if (!this->m_has_val && rhs.m_has_val) {
801 T tmp = rhs.get();
802 geterr().~unexpected<E>();
803 construct(std::move(tmp));
804 } else {
805 assign_common(rhs);
806 }
807 }
808
809 // This overload is the worst-case, where we have to move-construct the
810 // unexpected value into temporary storage, then try to copy the T into place.
811 // If the construction succeeds, then everything is fine, but if it throws,
812 // then we move the old unexpected value back into place before rethrowing the
813 // exception.
814 template <class U = T,
815 detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
816 !std::is_nothrow_move_constructible<U>::value>
817 * = nullptr>
818 void assign(const expected_operations_base &rhs) {
819 if (!this->m_has_val && rhs.m_has_val) {
820 auto tmp = std::move(geterr());
821 geterr().~unexpected<E>();
822
823#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
824 try {
825 construct(rhs.get());
826 } catch (...) {
827 geterr() = std::move(tmp);
828 throw;
829 }
830#else
831 construct(rhs.get());
832#endif
833 } else {
834 assign_common(rhs);
835 }
836 }
837
838 // These overloads do the same as above, but for rvalues
839 template <class U = T,
840 detail::enable_if_t<std::is_nothrow_move_constructible<U>::value>
841 * = nullptr>
842 void assign(expected_operations_base &&rhs) noexcept {
843 if (!this->m_has_val && rhs.m_has_val) {
844 geterr().~unexpected<E>();
845 construct(std::move(rhs).get());
846 } else {
847 assign_common(std::move(rhs));
848 }
849 }
850
851 template <class U = T,
852 detail::enable_if_t<!std::is_nothrow_move_constructible<U>::value>
853 * = nullptr>
854 void assign(expected_operations_base &&rhs) {
855 if (!this->m_has_val && rhs.m_has_val) {
856 auto tmp = std::move(geterr());
857 geterr().~unexpected<E>();
858#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
859 try {
860 construct(std::move(rhs).get());
861 } catch (...) {
862 geterr() = std::move(tmp);
863 throw;
864 }
865#else
866 construct(std::move(rhs).get());
867#endif
868 } else {
869 assign_common(std::move(rhs));
870 }
871 }
872
873#else
874
875 // If exceptions are disabled then we can just copy-construct
876 void assign(const expected_operations_base &rhs) noexcept {
877 if (!this->m_has_val && rhs.m_has_val) {
878 geterr().~unexpected<E>();
879 construct(rhs.get());
880 } else {
882 }
883 }
884
886 if (!this->m_has_val && rhs.m_has_val) {
887 geterr().~unexpected<E>();
888 construct(std::move(rhs).get());
889 } else {
891 }
892 }
893
894#endif
895
896 // The common part of move/copy assigning
897 template <class Rhs> void assign_common(Rhs &&rhs) {
898 if (this->m_has_val) {
899 if (rhs.m_has_val) {
900 get() = std::forward<Rhs>(rhs).get();
901 } else {
903 construct_error(std::forward<Rhs>(rhs).geterr());
904 }
905 } else {
906 if (!rhs.m_has_val) {
907 geterr() = std::forward<Rhs>(rhs).geterr();
908 }
909 }
910 }
911
912 bool has_value() const { return this->m_has_val; }
913
914 TL_EXPECTED_11_CONSTEXPR T &get() & { return this->m_val; }
915 constexpr const T &get() const & { return this->m_val; }
916 TL_EXPECTED_11_CONSTEXPR T &&get() && { return std::move(this->m_val); }
917#ifndef TL_EXPECTED_NO_CONSTRR
918 constexpr const T &&get() const && { return std::move(this->m_val); }
919#endif
920
922 return this->m_unexpect;
923 }
924 constexpr const unexpected<E> &geterr() const & { return this->m_unexpect; }
926 return std::move(this->m_unexpect);
927 }
928#ifndef TL_EXPECTED_NO_CONSTRR
929 constexpr const unexpected<E> &&geterr() const && {
930 return std::move(this->m_unexpect);
931 }
932#endif
933
935};
936
937// This base class provides some handy member functions which can be used in
938// further derived classes
939template <class E>
942
943 template <class... Args> void construct() noexcept { this->m_has_val = true; }
944
945 // This function doesn't use its argument, but needs it so that code in
946 // levels above this can work independently of whether T is void
947 template <class Rhs> void construct_with(Rhs &&) noexcept {
948 this->m_has_val = true;
949 }
950
951 template <class... Args> void construct_error(Args &&...args) noexcept {
952 new (std::addressof(this->m_unexpect))
953 unexpected<E>(std::forward<Args>(args)...);
954 this->m_has_val = false;
955 }
956
957 template <class Rhs> void assign(Rhs &&rhs) noexcept {
958 if (!this->m_has_val) {
959 if (rhs.m_has_val) {
960 geterr().~unexpected<E>();
961 construct();
962 } else {
963 geterr() = std::forward<Rhs>(rhs).geterr();
964 }
965 } else {
966 if (!rhs.m_has_val) {
967 construct_error(std::forward<Rhs>(rhs).geterr());
968 }
969 }
970 }
971
972 bool has_value() const { return this->m_has_val; }
973
975 return this->m_unexpect;
976 }
977 constexpr const unexpected<E> &geterr() const & { return this->m_unexpect; }
979 return std::move(this->m_unexpect);
980 }
981#ifndef TL_EXPECTED_NO_CONSTRR
982 constexpr const unexpected<E> &&geterr() const && {
983 return std::move(this->m_unexpect);
984 }
985#endif
986
988 // no-op
989 }
990};
991
992// This class manages conditionally having a trivial copy constructor
993// This specialization is for when T and E are trivially copy constructible
994template <class T, class E,
1002
1003// This specialization is for when T or E are non-trivially copy constructible
1004template <class T, class E>
1005struct expected_copy_base<T, E, false, true> : expected_operations_base<T, E> {
1007
1011 if (rhs.has_value()) {
1012 this->construct_with(rhs);
1013 } else {
1014 this->construct_error(rhs.geterr());
1015 }
1016 }
1017
1021};
1022
1023// This class manages conditionally having a trivial move constructor
1024// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
1025// doesn't implement an analogue to std::is_trivially_move_constructible. We
1026// have to make do with a non-trivial move constructor even if T is trivially
1027// move constructible
1028#ifndef TL_EXPECTED_GCC49
1029template <class T, class E,
1035#else
1036template <class T, class E, bool = false> struct expected_move_base;
1037#endif
1038template <class T, class E>
1039struct expected_move_base<T, E, false> : expected_copy_base<T, E> {
1041
1044
1048 if (rhs.has_value()) {
1049 this->construct_with(std::move(rhs));
1050 } else {
1051 this->construct_error(std::move(rhs.geterr()));
1052 }
1053 }
1056};
1057
1058// This class manages conditionally having a trivial copy assignment operator
1059template <class T, class E,
1060 bool = is_void_or<
1074
1075template <class T, class E>
1090
1091// This class manages conditionally having a trivial move assignment operator
1092// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
1093// doesn't implement an analogue to std::is_trivially_move_assignable. We have
1094// to make do with a non-trivial move assignment operator even if T is trivially
1095// move assignable
1096#ifndef TL_EXPECTED_GCC49
1097template <class T, class E,
1098 bool =
1108#else
1109template <class T, class E, bool = false> struct expected_move_assign_base;
1110#endif
1111
1112template <class T, class E>
1133
1134// expected_delete_ctor_base will conditionally delete copy and move
1135// constructors depending on whether T is copy/move constructible
1136template <class T, class E,
1137 bool EnableCopy = (is_copy_constructible_or_void<T>::value &&
1139 bool EnableMove = (is_move_constructible_or_void<T>::value &&
1150
1151template <class T, class E>
1161
1162template <class T, class E>
1172
1173template <class T, class E>
1183
1184// expected_delete_assign_base will conditionally delete copy and move
1185// constructors depending on whether T and E are copy/move constructible +
1186// assignable
1187template <class T, class E,
1188 bool EnableCopy = (is_copy_constructible_or_void<T>::value &&
1192 bool EnableMove = (is_move_constructible_or_void<T>::value &&
1206
1207template <class T, class E>
1218
1219template <class T, class E>
1230
1231template <class T, class E>
1242
1243// This is needed to be able to construct the expected_default_ctor_base which
1244// follows, while still conditionally deleting the default constructor.
1246 explicit constexpr default_constructor_tag() = default;
1247};
1248
1249// expected_default_ctor_base will ensure that expected has a deleted default
1250// constructor if T is not default constructible.
1251// This specialization is for when T is default constructible
1252template <class T, class E,
1253 bool Enable =
1254 std::is_default_constructible<T>::value || std::is_void<T>::value>
1256 constexpr expected_default_ctor_base() noexcept = default;
1258 expected_default_ctor_base const &) noexcept = default;
1260 default;
1262 operator=(expected_default_ctor_base const &) noexcept = default;
1264 operator=(expected_default_ctor_base &&) noexcept = default;
1265
1267};
1268
1269// This specialization is for when T is not default constructible
1270template <class T, class E> struct expected_default_ctor_base<T, E, false> {
1271 constexpr expected_default_ctor_base() noexcept = delete;
1273 expected_default_ctor_base const &) noexcept = default;
1275 default;
1277 operator=(expected_default_ctor_base const &) noexcept = default;
1279 operator=(expected_default_ctor_base &&) noexcept = default;
1280
1282};
1283} // namespace detail
1284
1285template <class E> class bad_expected_access : public std::exception {
1286public:
1287 explicit bad_expected_access(E e) : m_val(std::move(e)) {}
1288
1289 virtual const char *what() const noexcept override {
1290 return "Bad expected access";
1291 }
1292
1293 const E &error() const & { return m_val; }
1294 E &error() & { return m_val; }
1295 const E &&error() const && { return std::move(m_val); }
1296 E &&error() && { return std::move(m_val); }
1297
1298private:
1299 E m_val;
1300};
1301
1302/// An `expected<T, E>` object is an object that contains the storage for
1303/// another object and manages the lifetime of this contained object `T`.
1304/// Alternatively it could contain the storage for another unexpected object
1305/// `E`. The contained object may not be initialized after the expected object
1306/// has been initialized, and may not be destroyed before the expected object
1307/// has been destroyed. The initialization state of the contained object is
1308/// tracked by the expected object.
1309template <class T, class E>
1314 static_assert(!std::is_reference<T>::value, "T must not be a reference");
1315 static_assert(!std::is_same<T, std::remove_cv<in_place_t>::type>::value,
1316 "T must not be in_place_t");
1317 static_assert(!std::is_same<T, std::remove_cv<unexpect_t>::type>::value,
1318 "T must not be unexpect_t");
1319 static_assert(
1320 !std::is_same<T, typename std::remove_cv<unexpected<E>>::type>::value,
1321 "T must not be unexpected<E>");
1322 static_assert(!std::is_reference<E>::value, "E must not be a reference");
1323
1324 T *valptr() { return std::addressof(this->m_val); }
1325 const T *valptr() const { return std::addressof(this->m_val); }
1326 unexpected<E> *errptr() { return std::addressof(this->m_unexpect); }
1327 const unexpected<E> *errptr() const {
1328 return std::addressof(this->m_unexpect);
1329 }
1330
1331 template <class U = T,
1332 detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
1333 TL_EXPECTED_11_CONSTEXPR U &val() {
1334 return this->m_val;
1335 }
1336 TL_EXPECTED_11_CONSTEXPR unexpected<E> &err() { return this->m_unexpect; }
1337
1338 template <class U = T,
1339 detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
1340 constexpr const U &val() const {
1341 return this->m_val;
1342 }
1343 constexpr const unexpected<E> &err() const { return this->m_unexpect; }
1344
1347
1348public:
1349 typedef T value_type;
1350 typedef E error_type;
1352
1353#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) &&
1354 !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)
1355 template <class F> TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & {
1356 return and_then_impl(*this, std::forward<F>(f));
1357 }
1358 template <class F> TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && {
1359 return and_then_impl(std::move(*this), std::forward<F>(f));
1360 }
1361 template <class F> constexpr auto and_then(F &&f) const & {
1362 return and_then_impl(*this, std::forward<F>(f));
1363 }
1364
1365#ifndef TL_EXPECTED_NO_CONSTRR
1366 template <class F> constexpr auto and_then(F &&f) const && {
1367 return and_then_impl(std::move(*this), std::forward<F>(f));
1368 }
1369#endif
1370
1371#else
1372 template <class F>
1374 and_then(F &&f) & -> decltype(and_then_impl(std::declval<expected &>(),
1375 std::forward<F>(f))) {
1376 return and_then_impl(*this, std::forward<F>(f));
1377 }
1378 template <class F>
1380 and_then(F &&f) && -> decltype(and_then_impl(std::declval<expected &&>(),
1381 std::forward<F>(f))) {
1382 return and_then_impl(std::move(*this), std::forward<F>(f));
1383 }
1384 template <class F>
1385 constexpr auto and_then(F &&f) const & -> decltype(and_then_impl(
1386 std::declval<expected const &>(), std::forward<F>(f))) {
1387 return and_then_impl(*this, std::forward<F>(f));
1388 }
1389
1390#ifndef TL_EXPECTED_NO_CONSTRR
1391 template <class F>
1392 constexpr auto and_then(F &&f) const && -> decltype(and_then_impl(
1393 std::declval<expected const &&>(), std::forward<F>(f))) {
1394 return and_then_impl(std::move(*this), std::forward<F>(f));
1395 }
1396#endif
1397#endif
1398
1399#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) &&
1400 !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)
1401 template <class F> TL_EXPECTED_11_CONSTEXPR auto map(F &&f) & {
1402 return expected_map_impl(*this, std::forward<F>(f));
1403 }
1404 template <class F> TL_EXPECTED_11_CONSTEXPR auto map(F &&f) && {
1405 return expected_map_impl(std::move(*this), std::forward<F>(f));
1406 }
1407 template <class F> constexpr auto map(F &&f) const & {
1408 return expected_map_impl(*this, std::forward<F>(f));
1409 }
1410 template <class F> constexpr auto map(F &&f) const && {
1411 return expected_map_impl(std::move(*this), std::forward<F>(f));
1412 }
1413#else
1414 template <class F>
1416 std::declval<expected &>(), std::declval<F &&>()))
1417 map(F &&f) & {
1418 return expected_map_impl(*this, std::forward<F>(f));
1419 }
1420 template <class F>
1422 std::declval<F &&>()))
1423 map(F &&f) && {
1424 return expected_map_impl(std::move(*this), std::forward<F>(f));
1425 }
1426 template <class F>
1427 constexpr decltype(expected_map_impl(std::declval<const expected &>(),
1428 std::declval<F &&>()))
1429 map(F &&f) const & {
1430 return expected_map_impl(*this, std::forward<F>(f));
1431 }
1432
1433#ifndef TL_EXPECTED_NO_CONSTRR
1434 template <class F>
1435 constexpr decltype(expected_map_impl(std::declval<const expected &&>(),
1436 std::declval<F &&>()))
1437 map(F &&f) const && {
1438 return expected_map_impl(std::move(*this), std::forward<F>(f));
1439 }
1440#endif
1441#endif
1442
1443#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) &&
1444 !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)
1445 template <class F> TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) & {
1446 return expected_map_impl(*this, std::forward<F>(f));
1447 }
1448 template <class F> TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) && {
1449 return expected_map_impl(std::move(*this), std::forward<F>(f));
1450 }
1451 template <class F> constexpr auto transform(F &&f) const & {
1452 return expected_map_impl(*this, std::forward<F>(f));
1453 }
1454 template <class F> constexpr auto transform(F &&f) const && {
1455 return expected_map_impl(std::move(*this), std::forward<F>(f));
1456 }
1457#else
1458 template <class F>
1460 std::declval<expected &>(), std::declval<F &&>()))
1462 return expected_map_impl(*this, std::forward<F>(f));
1463 }
1464 template <class F>
1466 std::declval<F &&>()))
1467 transform(F &&f) && {
1468 return expected_map_impl(std::move(*this), std::forward<F>(f));
1469 }
1470 template <class F>
1471 constexpr decltype(expected_map_impl(std::declval<const expected &>(),
1472 std::declval<F &&>()))
1473 transform(F &&f) const & {
1474 return expected_map_impl(*this, std::forward<F>(f));
1475 }
1476
1477#ifndef TL_EXPECTED_NO_CONSTRR
1478 template <class F>
1479 constexpr decltype(expected_map_impl(std::declval<const expected &&>(),
1480 std::declval<F &&>()))
1481 transform(F &&f) const && {
1482 return expected_map_impl(std::move(*this), std::forward<F>(f));
1483 }
1484#endif
1485#endif
1486
1487#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) &&
1488 !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)
1489 template <class F> TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) & {
1490 return map_error_impl(*this, std::forward<F>(f));
1491 }
1492 template <class F> TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) && {
1493 return map_error_impl(std::move(*this), std::forward<F>(f));
1494 }
1495 template <class F> constexpr auto map_error(F &&f) const & {
1496 return map_error_impl(*this, std::forward<F>(f));
1497 }
1498 template <class F> constexpr auto map_error(F &&f) const && {
1499 return map_error_impl(std::move(*this), std::forward<F>(f));
1500 }
1501#else
1502 template <class F>
1504 std::declval<F &&>()))
1506 return map_error_impl(*this, std::forward<F>(f));
1507 }
1508 template <class F>
1510 std::declval<F &&>()))
1511 map_error(F &&f) && {
1512 return map_error_impl(std::move(*this), std::forward<F>(f));
1513 }
1514 template <class F>
1515 constexpr decltype(map_error_impl(std::declval<const expected &>(),
1516 std::declval<F &&>()))
1517 map_error(F &&f) const & {
1518 return map_error_impl(*this, std::forward<F>(f));
1519 }
1520
1521#ifndef TL_EXPECTED_NO_CONSTRR
1522 template <class F>
1523 constexpr decltype(map_error_impl(std::declval<const expected &&>(),
1524 std::declval<F &&>()))
1525 map_error(F &&f) const && {
1526 return map_error_impl(std::move(*this), std::forward<F>(f));
1527 }
1528#endif
1529#endif
1530#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) &&
1531 !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)
1532 template <class F> TL_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) & {
1533 return map_error_impl(*this, std::forward<F>(f));
1534 }
1535 template <class F> TL_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) && {
1536 return map_error_impl(std::move(*this), std::forward<F>(f));
1537 }
1538 template <class F> constexpr auto transform_error(F &&f) const & {
1539 return map_error_impl(*this, std::forward<F>(f));
1540 }
1541 template <class F> constexpr auto transform_error(F &&f) const && {
1542 return map_error_impl(std::move(*this), std::forward<F>(f));
1543 }
1544#else
1545 template <class F>
1547 std::declval<F &&>()))
1549 return map_error_impl(*this, std::forward<F>(f));
1550 }
1551 template <class F>
1553 std::declval<F &&>()))
1555 return map_error_impl(std::move(*this), std::forward<F>(f));
1556 }
1557 template <class F>
1558 constexpr decltype(map_error_impl(std::declval<const expected &>(),
1559 std::declval<F &&>()))
1560 transform_error(F &&f) const & {
1561 return map_error_impl(*this, std::forward<F>(f));
1562 }
1563
1564#ifndef TL_EXPECTED_NO_CONSTRR
1565 template <class F>
1566 constexpr decltype(map_error_impl(std::declval<const expected &&>(),
1567 std::declval<F &&>()))
1568 transform_error(F &&f) const && {
1569 return map_error_impl(std::move(*this), std::forward<F>(f));
1570 }
1571#endif
1572#endif
1573 template <class F> expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) & {
1574 return or_else_impl(*this, std::forward<F>(f));
1575 }
1576
1577 template <class F> expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) && {
1578 return or_else_impl(std::move(*this), std::forward<F>(f));
1579 }
1580
1581 template <class F> expected constexpr or_else(F &&f) const & {
1582 return or_else_impl(*this, std::forward<F>(f));
1583 }
1584
1585#ifndef TL_EXPECTED_NO_CONSTRR
1586 template <class F> expected constexpr or_else(F &&f) const && {
1587 return or_else_impl(std::move(*this), std::forward<F>(f));
1588 }
1589#endif
1590 constexpr expected() = default;
1591 constexpr expected(const expected &rhs) = default;
1592 constexpr expected(expected &&rhs) = default;
1593 expected &operator=(const expected &rhs) = default;
1594 expected &operator=(expected &&rhs) = default;
1595
1596 template <class... Args,
1597 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
1598 nullptr>
1599 constexpr expected(in_place_t, Args &&...args)
1602
1603 template <class U, class... Args,
1604 detail::enable_if_t<std::is_constructible<
1605 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
1606 constexpr expected(in_place_t, std::initializer_list<U> il, Args &&...args)
1609
1610 template <class G = E,
1611 detail::enable_if_t<std::is_constructible<E, const G &>::value> * =
1612 nullptr,
1613 detail::enable_if_t<!std::is_convertible<const G &, E>::value> * =
1614 nullptr>
1615 explicit constexpr expected(const unexpected<G> &e)
1616 : impl_base(unexpect, e.error()),
1618
1619 template <
1620 class G = E,
1621 detail::enable_if_t<std::is_constructible<E, const G &>::value> * =
1622 nullptr,
1623 detail::enable_if_t<std::is_convertible<const G &, E>::value> * = nullptr>
1624 constexpr expected(unexpected<G> const &e)
1625 : impl_base(unexpect, e.error()),
1627
1628 template <
1629 class G = E,
1630 detail::enable_if_t<std::is_constructible<E, G &&>::value> * = nullptr,
1631 detail::enable_if_t<!std::is_convertible<G &&, E>::value> * = nullptr>
1632 explicit constexpr expected(unexpected<G> &&e) noexcept(
1634 : impl_base(unexpect, std::move(e.error())),
1636
1637 template <
1638 class G = E,
1639 detail::enable_if_t<std::is_constructible<E, G &&>::value> * = nullptr,
1640 detail::enable_if_t<std::is_convertible<G &&, E>::value> * = nullptr>
1641 constexpr expected(unexpected<G> &&e) noexcept(
1643 : impl_base(unexpect, std::move(e.error())),
1645
1646 template <class... Args,
1647 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
1648 nullptr>
1649 constexpr explicit expected(unexpect_t, Args &&...args)
1652
1653 template <class U, class... Args,
1654 detail::enable_if_t<std::is_constructible<
1655 E, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
1656 constexpr explicit expected(unexpect_t, std::initializer_list<U> il,
1657 Args &&...args)
1660
1661 template <class U, class G,
1662 detail::enable_if_t<!(std::is_convertible<U const &, T>::value &&
1663 std::is_convertible<G const &, E>::value)> * =
1664 nullptr,
1665 detail::expected_enable_from_other<T, E, U, G, const U &, const G &>
1666 * = nullptr>
1667 explicit TL_EXPECTED_11_CONSTEXPR expected(const expected<U, G> &rhs)
1669 if (rhs.has_value()) {
1670 this->construct(*rhs);
1671 } else {
1672 this->construct_error(rhs.error());
1673 }
1674 }
1675
1676 template <class U, class G,
1677 detail::enable_if_t<(std::is_convertible<U const &, T>::value &&
1678 std::is_convertible<G const &, E>::value)> * =
1679 nullptr,
1680 detail::expected_enable_from_other<T, E, U, G, const U &, const G &>
1681 * = nullptr>
1684 if (rhs.has_value()) {
1685 this->construct(*rhs);
1686 } else {
1687 this->construct_error(rhs.error());
1688 }
1689 }
1690
1691 template <
1692 class U, class G,
1693 detail::enable_if_t<!(std::is_convertible<U &&, T>::value &&
1694 std::is_convertible<G &&, E>::value)> * = nullptr,
1695 detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * = nullptr>
1698 if (rhs.has_value()) {
1699 this->construct(std::move(*rhs));
1700 } else {
1701 this->construct_error(std::move(rhs.error()));
1702 }
1703 }
1704
1705 template <
1706 class U, class G,
1707 detail::enable_if_t<(std::is_convertible<U &&, T>::value &&
1708 std::is_convertible<G &&, E>::value)> * = nullptr,
1709 detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * = nullptr>
1712 if (rhs.has_value()) {
1713 this->construct(std::move(*rhs));
1714 } else {
1715 this->construct_error(std::move(rhs.error()));
1716 }
1717 }
1718
1719 template <
1720 class U = T,
1721 detail::enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr,
1722 detail::expected_enable_forward_value<T, E, U> * = nullptr>
1724 : expected(in_place, std::forward<U>(v)) {}
1725
1726 template <
1727 class U = T,
1728 detail::enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr,
1729 detail::expected_enable_forward_value<T, E, U> * = nullptr>
1732
1733 template <
1734 class U = T, class G = T,
1735 detail::enable_if_t<std::is_nothrow_constructible<T, U &&>::value> * =
1736 nullptr,
1737 detail::enable_if_t<!std::is_void<G>::value> * = nullptr,
1738 detail::enable_if_t<
1739 (!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
1740 !detail::conjunction<std::is_scalar<T>,
1741 std::is_same<T, detail::decay_t<U>>>::value &&
1742 std::is_constructible<T, U>::value &&
1743 std::is_assignable<G &, U>::value &&
1744 std::is_nothrow_move_constructible<E>::value)> * = nullptr>
1746 if (has_value()) {
1747 val() = std::forward<U>(v);
1748 } else {
1749 err().~unexpected<E>();
1750 ::new (valptr()) T(std::forward<U>(v));
1751 this->m_has_val = true;
1752 }
1753
1754 return *this;
1755 }
1756
1757 template <
1758 class U = T, class G = T,
1759 detail::enable_if_t<!std::is_nothrow_constructible<T, U &&>::value> * =
1760 nullptr,
1761 detail::enable_if_t<!std::is_void<U>::value> * = nullptr,
1762 detail::enable_if_t<
1763 (!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
1764 !detail::conjunction<std::is_scalar<T>,
1765 std::is_same<T, detail::decay_t<U>>>::value &&
1766 std::is_constructible<T, U>::value &&
1767 std::is_assignable<G &, U>::value &&
1768 std::is_nothrow_move_constructible<E>::value)> * = nullptr>
1770 if (has_value()) {
1771 val() = std::forward<U>(v);
1772 } else {
1773 auto tmp = std::move(err());
1774 err().~unexpected<E>();
1775
1776#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1777 try {
1778 ::new (valptr()) T(std::forward<U>(v));
1779 this->m_has_val = true;
1780 } catch (...) {
1781 err() = std::move(tmp);
1782 throw;
1783 }
1784#else
1785 ::new (valptr()) T(std::forward<U>(v));
1786 this->m_has_val = true;
1787#endif
1788 }
1789
1790 return *this;
1791 }
1792
1793 template <class G = E,
1794 detail::enable_if_t<std::is_nothrow_copy_constructible<G>::value &&
1795 std::is_assignable<G &, G>::value> * = nullptr>
1796 expected &operator=(const unexpected<G> &rhs) {
1797 if (!has_value()) {
1798 err() = rhs;
1799 } else {
1800 this->destroy_val();
1801 ::new (errptr()) unexpected<E>(rhs);
1802 this->m_has_val = false;
1803 }
1804
1805 return *this;
1806 }
1807
1808 template <class G = E,
1809 detail::enable_if_t<std::is_nothrow_move_constructible<G>::value &&
1810 std::is_move_assignable<G>::value> * = nullptr>
1811 expected &operator=(unexpected<G> &&rhs) noexcept {
1812 if (!has_value()) {
1813 err() = std::move(rhs);
1814 } else {
1815 this->destroy_val();
1816 ::new (errptr()) unexpected<E>(std::move(rhs));
1817 this->m_has_val = false;
1818 }
1819
1820 return *this;
1821 }
1822
1823 template <class... Args, detail::enable_if_t<std::is_nothrow_constructible<
1824 T, Args &&...>::value> * = nullptr>
1825 void emplace(Args &&...args) {
1826 if (has_value()) {
1827 val().~T();
1828 } else {
1829 err().~unexpected<E>();
1830 this->m_has_val = true;
1831 }
1832 ::new (valptr()) T(std::forward<Args>(args)...);
1833 }
1834
1835 template <class... Args, detail::enable_if_t<!std::is_nothrow_constructible<
1836 T, Args &&...>::value> * = nullptr>
1837 void emplace(Args &&...args) {
1838 if (has_value()) {
1839 val().~T();
1840 ::new (valptr()) T(std::forward<Args>(args)...);
1841 } else {
1842 auto tmp = std::move(err());
1843 err().~unexpected<E>();
1844
1845#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1846 try {
1847 ::new (valptr()) T(std::forward<Args>(args)...);
1848 this->m_has_val = true;
1849 } catch (...) {
1850 err() = std::move(tmp);
1851 throw;
1852 }
1853#else
1854 ::new (valptr()) T(std::forward<Args>(args)...);
1855 this->m_has_val = true;
1856#endif
1857 }
1858 }
1859
1860 template <class U, class... Args,
1861 detail::enable_if_t<std::is_nothrow_constructible<
1862 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
1863 void emplace(std::initializer_list<U> il, Args &&...args) {
1864 if (has_value()) {
1865 T t(il, std::forward<Args>(args)...);
1866 val() = std::move(t);
1867 } else {
1868 err().~unexpected<E>();
1869 ::new (valptr()) T(il, std::forward<Args>(args)...);
1870 this->m_has_val = true;
1871 }
1872 }
1873
1874 template <class U, class... Args,
1875 detail::enable_if_t<!std::is_nothrow_constructible<
1876 T, std::initializer_list<U> &, Args &&...>::value> * = nullptr>
1877 void emplace(std::initializer_list<U> il, Args &&...args) {
1878 if (has_value()) {
1879 T t(il, std::forward<Args>(args)...);
1880 val() = std::move(t);
1881 } else {
1882 auto tmp = std::move(err());
1883 err().~unexpected<E>();
1884
1885#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1886 try {
1887 ::new (valptr()) T(il, std::forward<Args>(args)...);
1888 this->m_has_val = true;
1889 } catch (...) {
1890 err() = std::move(tmp);
1891 throw;
1892 }
1893#else
1894 ::new (valptr()) T(il, std::forward<Args>(args)...);
1895 this->m_has_val = true;
1896#endif
1897 }
1898 }
1899
1900private:
1901 using t_is_void = std::true_type;
1902 using t_is_not_void = std::false_type;
1907
1908 void swap_where_both_have_value(expected & /*rhs*/, t_is_void) noexcept {
1909 // swapping void is a no-op
1910 }
1911
1912 void swap_where_both_have_value(expected &rhs, t_is_not_void) {
1913 using std::swap;
1914 swap(val(), rhs.val());
1915 }
1916
1917 void swap_where_only_one_has_value(expected &rhs, t_is_void) noexcept(
1918 std::is_nothrow_move_constructible<E>::value) {
1919 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1920 rhs.err().~unexpected_type();
1921 std::swap(this->m_has_val, rhs.m_has_val);
1922 }
1923
1924 void swap_where_only_one_has_value(expected &rhs, t_is_not_void) {
1925 swap_where_only_one_has_value_and_t_is_not_void(
1926 rhs, typename std::is_nothrow_move_constructible<T>::type{},
1927 typename std::is_nothrow_move_constructible<E>::type{});
1928 }
1929
1930 void swap_where_only_one_has_value_and_t_is_not_void(
1931 expected &rhs, t_is_nothrow_move_constructible,
1932 e_is_nothrow_move_constructible) noexcept {
1933 auto temp = std::move(val());
1934 val().~T();
1935 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1936 rhs.err().~unexpected_type();
1937 ::new (rhs.valptr()) T(std::move(temp));
1938 std::swap(this->m_has_val, rhs.m_has_val);
1939 }
1940
1941 void swap_where_only_one_has_value_and_t_is_not_void(
1942 expected &rhs, t_is_nothrow_move_constructible,
1943 move_constructing_e_can_throw) {
1944 auto temp = std::move(val());
1945 val().~T();
1946#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1947 try {
1948 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1949 rhs.err().~unexpected_type();
1950 ::new (rhs.valptr()) T(std::move(temp));
1951 std::swap(this->m_has_val, rhs.m_has_val);
1952 } catch (...) {
1953 val() = std::move(temp);
1954 throw;
1955 }
1956#else
1957 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1958 rhs.err().~unexpected_type();
1959 ::new (rhs.valptr()) T(std::move(temp));
1960 std::swap(this->m_has_val, rhs.m_has_val);
1961#endif
1962 }
1963
1964 void swap_where_only_one_has_value_and_t_is_not_void(
1965 expected &rhs, move_constructing_t_can_throw,
1966 e_is_nothrow_move_constructible) {
1967 auto temp = std::move(rhs.err());
1968 rhs.err().~unexpected_type();
1969#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
1970 try {
1971 ::new (rhs.valptr()) T(std::move(val()));
1972 val().~T();
1973 ::new (errptr()) unexpected_type(std::move(temp));
1974 std::swap(this->m_has_val, rhs.m_has_val);
1975 } catch (...) {
1976 rhs.err() = std::move(temp);
1977 throw;
1978 }
1979#else
1980 ::new (rhs.valptr()) T(std::move(val()));
1981 val().~T();
1982 ::new (errptr()) unexpected_type(std::move(temp));
1983 std::swap(this->m_has_val, rhs.m_has_val);
1984#endif
1985 }
1986
1987public:
1988 template <class OT = T, class OE = E>
1993 swap(expected &rhs) noexcept(
1998 if (has_value() && rhs.has_value()) {
1999 swap_where_both_have_value(rhs, typename std::is_void<T>::type{});
2000 } else if (!has_value() && rhs.has_value()) {
2001 rhs.swap(*this);
2002 } else if (has_value()) {
2003 swap_where_only_one_has_value(rhs, typename std::is_void<T>::type{});
2004 } else {
2005 using std::swap;
2006 swap(err(), rhs.err());
2007 }
2008 }
2009
2010 constexpr const T *operator->() const {
2012 return valptr();
2013 }
2016 return valptr();
2017 }
2018
2019 template <class U = T,
2020 detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
2021 constexpr const U &operator*() const & {
2023 return val();
2024 }
2025 template <class U = T,
2026 detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
2029 return val();
2030 }
2031 template <class U = T,
2032 detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
2033 constexpr const U &&operator*() const && {
2035 return std::move(val());
2036 }
2037 template <class U = T,
2038 detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
2041 return std::move(val());
2042 }
2043
2044 constexpr bool has_value() const noexcept { return this->m_has_val; }
2045 constexpr explicit operator bool() const noexcept { return this->m_has_val; }
2046
2047 template <class U = T,
2048 detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
2049 TL_EXPECTED_11_CONSTEXPR const U &value() const & {
2050 if (!has_value())
2051 detail::throw_exception(bad_expected_access<E>(err().error()));
2052 return val();
2053 }
2054 template <class U = T,
2055 detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
2057 if (!has_value())
2058 detail::throw_exception(bad_expected_access<E>(err().error()));
2059 return val();
2060 }
2061 template <class U = T,
2062 detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
2063 TL_EXPECTED_11_CONSTEXPR const U &&value() const && {
2064 if (!has_value())
2065 detail::throw_exception(bad_expected_access<E>(std::move(err()).error()));
2066 return std::move(val());
2067 }
2068 template <class U = T,
2069 detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
2071 if (!has_value())
2072 detail::throw_exception(bad_expected_access<E>(std::move(err()).error()));
2073 return std::move(val());
2074 }
2075
2076 constexpr const E &error() const & {
2078 return err().error();
2079 }
2082 return err().error();
2083 }
2084 constexpr const E &&error() const && {
2086 return std::move(err().error());
2087 }
2090 return std::move(err().error());
2091 }
2092
2093 template <class U> constexpr T value_or(U &&v) const & {
2094 static_assert(std::is_copy_constructible<T>::value &&
2095 std::is_convertible<U &&, T>::value,
2096 "T must be copy-constructible and convertible to from U&&");
2097 return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));
2098 }
2099 template <class U> TL_EXPECTED_11_CONSTEXPR T value_or(U &&v) && {
2100 static_assert(std::is_move_constructible<T>::value &&
2101 std::is_convertible<U &&, T>::value,
2102 "T must be move-constructible and convertible to from U&&");
2103 return bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(v));
2104 }
2105};
2106
2107namespace detail {
2108template <class Exp> using exp_t = typename detail::decay_t<Exp>::value_type;
2109template <class Exp> using err_t = typename detail::decay_t<Exp>::error_type;
2110template <class Exp, class Ret> using ret_t = expected<Ret, err_t<Exp>>;
2111
2112#ifdef TL_EXPECTED_CXX14
2113template <class Exp, class F,
2114 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2115 class Ret = decltype(detail::invoke(std::declval<F>(),
2116 *std::declval<Exp>()))>
2117constexpr auto and_then_impl(Exp &&exp, F &&f) {
2118 static_assert(detail::is_expected<Ret>::value, "F must return an expected");
2119
2120 return exp.has_value()
2121 ? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
2122 : Ret(unexpect, std::forward<Exp>(exp).error());
2123}
2124
2125template <class Exp, class F,
2126 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2127 class Ret = decltype(detail::invoke(std::declval<F>()))>
2128constexpr auto and_then_impl(Exp &&exp, F &&f) {
2129 static_assert(detail::is_expected<Ret>::value, "F must return an expected");
2130
2131 return exp.has_value() ? detail::invoke(std::forward<F>(f))
2132 : Ret(unexpect, std::forward<Exp>(exp).error());
2133}
2134#else
2135template <class> struct TC;
2136template <class Exp, class F,
2137 class Ret = decltype(detail::invoke(std::declval<F>(),
2138 *std::declval<Exp>())),
2139 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr>
2140auto and_then_impl(Exp &&exp, F &&f) -> Ret {
2141 static_assert(detail::is_expected<Ret>::value, "F must return an expected");
2142
2143 return exp.has_value()
2144 ? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
2145 : Ret(unexpect, std::forward<Exp>(exp).error());
2146}
2147
2148template <class Exp, class F,
2149 class Ret = decltype(detail::invoke(std::declval<F>())),
2150 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr>
2151constexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret {
2152 static_assert(detail::is_expected<Ret>::value, "F must return an expected");
2153
2154 return exp.has_value() ? detail::invoke(std::forward<F>(f))
2155 : Ret(unexpect, std::forward<Exp>(exp).error());
2156}
2157#endif
2158
2159#ifdef TL_EXPECTED_CXX14
2160template <class Exp, class F,
2161 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2162 class Ret = decltype(detail::invoke(std::declval<F>(),
2163 *std::declval<Exp>())),
2164 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2165constexpr auto expected_map_impl(Exp &&exp, F &&f) {
2166 using result = ret_t<Exp, detail::decay_t<Ret>>;
2167 return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
2168 *std::forward<Exp>(exp)))
2169 : result(unexpect, std::forward<Exp>(exp).error());
2170}
2171
2172template <class Exp, class F,
2173 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2174 class Ret = decltype(detail::invoke(std::declval<F>(),
2175 *std::declval<Exp>())),
2176 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2177auto expected_map_impl(Exp &&exp, F &&f) {
2178 using result = expected<void, err_t<Exp>>;
2179 if (exp.has_value()) {
2180 detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
2181 return result();
2182 }
2183
2184 return result(unexpect, std::forward<Exp>(exp).error());
2185}
2186
2187template <class Exp, class F,
2188 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2189 class Ret = decltype(detail::invoke(std::declval<F>())),
2190 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2191constexpr auto expected_map_impl(Exp &&exp, F &&f) {
2192 using result = ret_t<Exp, detail::decay_t<Ret>>;
2193 return exp.has_value() ? result(detail::invoke(std::forward<F>(f)))
2194 : result(unexpect, std::forward<Exp>(exp).error());
2195}
2196
2197template <class Exp, class F,
2198 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2199 class Ret = decltype(detail::invoke(std::declval<F>())),
2200 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2201auto expected_map_impl(Exp &&exp, F &&f) {
2202 using result = expected<void, err_t<Exp>>;
2203 if (exp.has_value()) {
2204 detail::invoke(std::forward<F>(f));
2205 return result();
2206 }
2207
2208 return result(unexpect, std::forward<Exp>(exp).error());
2209}
2210#else
2211template <class Exp, class F,
2212 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2213 class Ret = decltype(detail::invoke(std::declval<F>(),
2214 *std::declval<Exp>())),
2215 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2216
2217constexpr auto expected_map_impl(Exp &&exp, F &&f)
2218 -> ret_t<Exp, detail::decay_t<Ret>> {
2219 using result = ret_t<Exp, detail::decay_t<Ret>>;
2220
2221 return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
2222 *std::forward<Exp>(exp)))
2224}
2225
2226template <class Exp, class F,
2227 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2228 class Ret = decltype(detail::invoke(std::declval<F>(),
2229 *std::declval<Exp>())),
2230 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2231
2232auto expected_map_impl(Exp &&exp, F &&f) -> expected<void, err_t<Exp>> {
2233 if (exp.has_value()) {
2235 return {};
2236 }
2237
2238 return unexpected<err_t<Exp>>(std::forward<Exp>(exp).error());
2239}
2240
2241template <class Exp, class F,
2242 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2243 class Ret = decltype(detail::invoke(std::declval<F>())),
2244 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2245
2246constexpr auto expected_map_impl(Exp &&exp, F &&f)
2247 -> ret_t<Exp, detail::decay_t<Ret>> {
2248 using result = ret_t<Exp, detail::decay_t<Ret>>;
2249
2250 return exp.has_value() ? result(detail::invoke(std::forward<F>(f)))
2252}
2253
2254template <class Exp, class F,
2255 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2256 class Ret = decltype(detail::invoke(std::declval<F>())),
2257 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2258
2259auto expected_map_impl(Exp &&exp, F &&f) -> expected<void, err_t<Exp>> {
2260 if (exp.has_value()) {
2261 detail::invoke(std::forward<F>(f));
2262 return {};
2263 }
2264
2265 return unexpected<err_t<Exp>>(std::forward<Exp>(exp).error());
2266}
2267#endif
2268
2269#if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) &&
2270 !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55)
2271template <class Exp, class F,
2272 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2273 class Ret = decltype(detail::invoke(std::declval<F>(),
2274 std::declval<Exp>().error())),
2275 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2276constexpr auto map_error_impl(Exp &&exp, F &&f) {
2277 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2278 return exp.has_value()
2279 ? result(*std::forward<Exp>(exp))
2280 : result(unexpect, detail::invoke(std::forward<F>(f),
2281 std::forward<Exp>(exp).error()));
2282}
2283template <class Exp, class F,
2284 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2285 class Ret = decltype(detail::invoke(std::declval<F>(),
2286 std::declval<Exp>().error())),
2287 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2288auto map_error_impl(Exp &&exp, F &&f) {
2289 using result = expected<exp_t<Exp>, monostate>;
2290 if (exp.has_value()) {
2291 return result(*std::forward<Exp>(exp));
2292 }
2293
2294 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2295 return result(unexpect, monostate{});
2296}
2297template <class Exp, class F,
2298 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2299 class Ret = decltype(detail::invoke(std::declval<F>(),
2300 std::declval<Exp>().error())),
2301 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2302constexpr auto map_error_impl(Exp &&exp, F &&f) {
2303 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2304 return exp.has_value()
2305 ? result()
2306 : result(unexpect, detail::invoke(std::forward<F>(f),
2307 std::forward<Exp>(exp).error()));
2308}
2309template <class Exp, class F,
2310 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2311 class Ret = decltype(detail::invoke(std::declval<F>(),
2312 std::declval<Exp>().error())),
2313 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2314auto map_error_impl(Exp &&exp, F &&f) {
2315 using result = expected<exp_t<Exp>, monostate>;
2316 if (exp.has_value()) {
2317 return result();
2318 }
2319
2320 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2321 return result(unexpect, monostate{});
2322}
2323#else
2324template <class Exp, class F,
2325 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2326 class Ret = decltype(detail::invoke(std::declval<F>(),
2327 std::declval<Exp>().error())),
2328 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2329constexpr auto map_error_impl(Exp &&exp, F &&f)
2331 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2332
2333 return exp.has_value()
2334 ? result(*std::forward<Exp>(exp))
2336 std::forward<Exp>(exp).error()));
2337}
2338
2339template <class Exp, class F,
2340 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr,
2341 class Ret = decltype(detail::invoke(std::declval<F>(),
2342 std::declval<Exp>().error())),
2343 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2345 using result = expected<exp_t<Exp>, monostate>;
2346 if (exp.has_value()) {
2347 return result(*std::forward<Exp>(exp));
2348 }
2349
2351 return result(unexpect, monostate{});
2352}
2353
2354template <class Exp, class F,
2355 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2356 class Ret = decltype(detail::invoke(std::declval<F>(),
2357 std::declval<Exp>().error())),
2358 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2359constexpr auto map_error_impl(Exp &&exp, F &&f)
2361 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2362
2363 return exp.has_value()
2364 ? result()
2366 std::forward<Exp>(exp).error()));
2367}
2368
2369template <class Exp, class F,
2370 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr,
2371 class Ret = decltype(detail::invoke(std::declval<F>(),
2372 std::declval<Exp>().error())),
2373 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2375 using result = expected<exp_t<Exp>, monostate>;
2376 if (exp.has_value()) {
2377 return result();
2378 }
2379
2381 return result(unexpect, monostate{});
2382}
2383#endif
2384
2385#ifdef TL_EXPECTED_CXX14
2386template <class Exp, class F,
2387 class Ret = decltype(detail::invoke(std::declval<F>(),
2388 std::declval<Exp>().error())),
2389 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2390constexpr auto or_else_impl(Exp &&exp, F &&f) {
2391 static_assert(detail::is_expected<Ret>::value, "F must return an expected");
2392 return exp.has_value() ? std::forward<Exp>(exp)
2393 : detail::invoke(std::forward<F>(f),
2394 std::forward<Exp>(exp).error());
2395}
2396
2397template <class Exp, class F,
2398 class Ret = decltype(detail::invoke(std::declval<F>(),
2399 std::declval<Exp>().error())),
2400 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2401detail::decay_t<Exp> or_else_impl(Exp &&exp, F &&f) {
2402 return exp.has_value() ? std::forward<Exp>(exp)
2403 : (detail::invoke(std::forward<F>(f),
2404 std::forward<Exp>(exp).error()),
2405 std::forward<Exp>(exp));
2406}
2407#else
2408template <class Exp, class F,
2409 class Ret = decltype(detail::invoke(std::declval<F>(),
2410 std::declval<Exp>().error())),
2411 detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
2412auto or_else_impl(Exp &&exp, F &&f) -> Ret {
2413 static_assert(detail::is_expected<Ret>::value, "F must return an expected");
2414 return exp.has_value() ? std::forward<Exp>(exp)
2415 : detail::invoke(std::forward<F>(f),
2416 std::forward<Exp>(exp).error());
2417}
2418
2419template <class Exp, class F,
2420 class Ret = decltype(detail::invoke(std::declval<F>(),
2421 std::declval<Exp>().error())),
2422 detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
2424 return exp.has_value() ? std::forward<Exp>(exp)
2425 : (detail::invoke(std::forward<F>(f),
2426 std::forward<Exp>(exp).error()),
2427 std::forward<Exp>(exp));
2428}
2429#endif
2430} // namespace detail
2431
2432template <class T, class E, class U, class F>
2433constexpr bool operator==(const expected<T, E> &lhs,
2434 const expected<U, F> &rhs) {
2435 return (lhs.has_value() != rhs.has_value())
2436 ? false
2437 : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs);
2438}
2439template <class T, class E, class U, class F>
2440constexpr bool operator!=(const expected<T, E> &lhs,
2441 const expected<U, F> &rhs) {
2442 return (lhs.has_value() != rhs.has_value())
2443 ? true
2444 : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs);
2445}
2446template <class E, class F>
2447constexpr bool operator==(const expected<void, E> &lhs,
2448 const expected<void, F> &rhs) {
2449 return (lhs.has_value() != rhs.has_value())
2450 ? false
2451 : (!lhs.has_value() ? lhs.error() == rhs.error() : true);
2452}
2453template <class E, class F>
2454constexpr bool operator!=(const expected<void, E> &lhs,
2455 const expected<void, F> &rhs) {
2456 return (lhs.has_value() != rhs.has_value())
2457 ? true
2458 : (!lhs.has_value() ? lhs.error() != rhs.error() : false);
2459}
2460
2461template <class T, class E, class U>
2462constexpr bool operator==(const expected<T, E> &x, const U &v) {
2463 return x.has_value() ? *x == v : false;
2464}
2465template <class T, class E, class U>
2466constexpr bool operator==(const U &v, const expected<T, E> &x) {
2467 return x.has_value() ? *x == v : false;
2468}
2469template <class T, class E, class U>
2470constexpr bool operator!=(const expected<T, E> &x, const U &v) {
2471 return x.has_value() ? *x != v : true;
2472}
2473template <class T, class E, class U>
2474constexpr bool operator!=(const U &v, const expected<T, E> &x) {
2475 return x.has_value() ? *x != v : true;
2476}
2477
2478template <class T, class E>
2479constexpr bool operator==(const expected<T, E> &x, const unexpected<E> &e) {
2480 return x.has_value() ? false : x.error() == e.error();
2481}
2482template <class T, class E>
2483constexpr bool operator==(const unexpected<E> &e, const expected<T, E> &x) {
2484 return x.has_value() ? false : x.error() == e.error();
2485}
2486template <class T, class E>
2487constexpr bool operator!=(const expected<T, E> &x, const unexpected<E> &e) {
2488 return x.has_value() ? true : x.error() != e.error();
2489}
2490template <class T, class E>
2491constexpr bool operator!=(const unexpected<E> &e, const expected<T, E> &x) {
2492 return x.has_value() ? true : x.error() != e.error();
2493}
2494
2495template <class T, class E,
2496 detail::enable_if_t<(std::is_void<T>::value ||
2497 std::is_move_constructible<T>::value) &&
2498 detail::is_swappable<T>::value &&
2499 std::is_move_constructible<E>::value &&
2500 detail::is_swappable<E>::value> * = nullptr>
2501void swap(expected<T, E> &lhs,
2502 expected<T, E> &rhs) noexcept(noexcept(lhs.swap(rhs))) {
2503 lhs.swap(rhs);
2504}
2505} // namespace q23
2506QT_END_NAMESPACE
2507
2508#endif
const E && error() const &&
virtual const char * what() const noexcept override
const E & error() const &
TL_EXPECTED_11_CONSTEXPR E && error() &&
expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) &
constexpr T value_or(U &&v) const &
TL_EXPECTED_11_CONSTEXPR const U & value() const &
constexpr const E && error() const &&
expected constexpr or_else(F &&f) const &&
constexpr expected(unexpect_t, Args &&...args)
TL_EXPECTED_11_CONSTEXPR expected(expected< U, G > &&rhs)
constexpr expected(in_place_t, std::initializer_list< U > il, Args &&...args)
constexpr const U & operator*() const &
expected & operator=(const unexpected< G > &rhs)
constexpr expected(const expected &rhs)=default
unexpected< E > unexpected_type
TL_EXPECTED_11_CONSTEXPR T * operator->()
expected & operator=(expected &&rhs)=default
TL_EXPECTED_11_CONSTEXPR E & error() &
TL_EXPECTED_11_CONSTEXPR U & value() &
TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v)
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)
void emplace(std::initializer_list< U > il, Args &&...args)
constexpr expected(unexpect_t, std::initializer_list< U > il, Args &&...args)
expected constexpr or_else(F &&f) const &
constexpr bool has_value() const noexcept
TL_EXPECTED_11_CONSTEXPR U && operator*() &&
constexpr expected()=default
TL_EXPECTED_11_CONSTEXPR expected(const expected< U, G > &rhs)
constexpr expected(in_place_t, Args &&...args)
void emplace(Args &&...args)
constexpr const E & error() const &
constexpr expected(unexpected< G > &&e) noexcept(std::is_nothrow_constructible< E, G && >::value)
constexpr const T * operator->() const
TL_EXPECTED_11_CONSTEXPR T value_or(U &&v) &&
expected & operator=(unexpected< G > &&rhs) noexcept
constexpr expected(const unexpected< G > &e)
constexpr const U && operator*() const &&
TL_EXPECTED_11_CONSTEXPR U & operator*() &
TL_EXPECTED_11_CONSTEXPR const U && value() const &&
expected & operator=(U &&v)
expected & operator=(const expected &rhs)=default
constexpr operator bool() const noexcept
constexpr expected(expected &&rhs)=default
TL_EXPECTED_11_CONSTEXPR U && value() &&
expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) &&
constexpr unexpected(in_place_t, Args &&...args)
constexpr unexpected(const E &e)
constexpr const E & error() const &
TL_EXPECTED_11_CONSTEXPR E && error() &&
TL_EXPECTED_11_CONSTEXPR E & error() &
unexpected()=delete
constexpr unexpected(in_place_t, std::initializer_list< U > l, Args &&...args)
constexpr const E && error() const &&
constexpr unexpected(E &&e)
std::is_same< decltype(swap(std::declval< T & >(), std::declval< U & >())), tag > uses_std(int)
std::false_type can_swap(...) noexcept(false)
tag swap(T(&a)[N], T(&b)[N])
std::true_type can_swap(int) noexcept(noexcept(swap(std::declval< T & >(), std::declval< U & >())))
std::false_type uses_std(...)
constexpr auto invoke(Fn &&f, Args &&...args) noexcept(noexcept(std::forward< Fn >(f)(std::forward< Args >(args)...))) -> decltype(std::forward< Fn >(f)(std::forward< Args >(args)...))
typename std::conditional< B, T, F >::type conditional_t
invoke_result_impl< F, void, Us... > invoke_result
typename std::remove_reference< T >::type remove_reference_t
typename std::enable_if< E, T >::type enable_if_t
static constexpr no_init_t no_init
TL_EXPECTED_11_CONSTEXPR void throw_exception(E &&e)
typename std::decay< T >::type decay_t
typename std::remove_const< T >::type remove_const_t
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)...))
constexpr bool operator!=(const unexpected< E > &e, const expected< T, E > &x)
constexpr bool operator!=(const unexpected< E > &lhs, const unexpected< E > &rhs)
constexpr bool operator<(const unexpected< E > &lhs, const unexpected< E > &rhs)
constexpr bool operator>(const unexpected< E > &lhs, const unexpected< E > &rhs)
constexpr bool operator==(const unexpected< E > &lhs, const unexpected< E > &rhs)
constexpr bool operator==(const expected< void, E > &lhs, const expected< void, F > &rhs)
constexpr bool operator!=(const expected< T, E > &lhs, const expected< U, F > &rhs)
unexpected< typename std::decay< E >::type > make_unexpected(E &&e)
constexpr bool operator<=(const unexpected< E > &lhs, const unexpected< E > &rhs)
void swap(expected< T, E > &lhs, expected< T, E > &rhs) noexcept(noexcept(lhs.swap(rhs)))
constexpr bool operator!=(const expected< T, E > &x, const U &v)
constexpr bool operator==(const unexpected< E > &e, const expected< T, E > &x)
constexpr bool operator==(const expected< T, E > &x, const U &v)
constexpr bool operator==(const U &v, const expected< T, E > &x)
static constexpr unexpect_t unexpect
constexpr bool operator!=(const expected< T, E > &x, const unexpected< E > &e)
static constexpr in_place_t in_place
constexpr bool operator>=(const unexpected< E > &lhs, const unexpected< E > &rhs)
constexpr bool operator!=(const expected< void, E > &lhs, const expected< void, F > &rhs)
constexpr bool operator==(const expected< T, E > &x, const unexpected< E > &e)
constexpr bool operator==(const expected< T, E > &lhs, const expected< U, F > &rhs)
constexpr bool operator!=(const U &v, const expected< T, E > &x)
#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)
#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)
#define TL_EXPECTED_MSVC2015_CONSTEXPR
Definition qexpected_p.h:61
#define TL_CPLUSPLUS
#define TL_ASSERT
Definition qexpected_p.h:47
#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T)
#define TL_EXPECTED_11_CONSTEXPR
constexpr default_constructor_tag()=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)
expected_copy_assign_base & operator=(expected_copy_assign_base &&rhs)=default
expected_copy_base & operator=(const expected_copy_base &rhs)=default
expected_copy_base(const expected_copy_base &rhs)
expected_copy_base(expected_copy_base &&rhs)=default
expected_copy_base & operator=(expected_copy_base &&rhs)=default
constexpr expected_default_ctor_base(expected_default_ctor_base const &) noexcept=default
constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept=default
constexpr expected_default_ctor_base(default_constructor_tag)
expected_default_ctor_base & operator=(expected_default_ctor_base const &) noexcept=default
expected_default_ctor_base & operator=(expected_default_ctor_base &&) noexcept=default
expected_default_ctor_base & operator=(expected_default_ctor_base &&) noexcept=default
constexpr expected_default_ctor_base(expected_default_ctor_base const &) noexcept=default
expected_default_ctor_base & operator=(expected_default_ctor_base const &) noexcept=default
constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept=default
constexpr expected_default_ctor_base(default_constructor_tag)
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 & operator=(expected_delete_assign_base &&) noexcept=delete
expected_delete_assign_base & operator=(const expected_delete_assign_base &)=delete
expected_delete_assign_base(expected_delete_assign_base &&) noexcept=default
expected_delete_assign_base & operator=(expected_delete_assign_base &&) noexcept=default
expected_delete_assign_base & operator=(const expected_delete_assign_base &)=delete
expected_delete_assign_base(const expected_delete_assign_base &)=default
expected_delete_assign_base(expected_delete_assign_base &&) noexcept=default
expected_delete_assign_base & operator=(const expected_delete_assign_base &)=default
expected_delete_assign_base(const expected_delete_assign_base &)=default
expected_delete_assign_base & operator=(expected_delete_assign_base &&) noexcept=delete
expected_delete_assign_base(expected_delete_assign_base &&) noexcept=default
expected_delete_assign_base & operator=(const expected_delete_assign_base &)=default
expected_delete_assign_base & operator=(expected_delete_assign_base &&) noexcept=default
expected_delete_assign_base(const expected_delete_assign_base &)=default
expected_delete_ctor_base & operator=(expected_delete_ctor_base &&) noexcept=default
expected_delete_ctor_base & operator=(const expected_delete_ctor_base &)=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(const expected_delete_ctor_base &)=delete
expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept=default
expected_delete_ctor_base & operator=(const expected_delete_ctor_base &)=default
expected_delete_ctor_base & operator=(expected_delete_ctor_base &&) noexcept=default
expected_delete_ctor_base(const expected_delete_ctor_base &)=default
expected_delete_ctor_base & operator=(expected_delete_ctor_base &&) noexcept=default
expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept=delete
expected_delete_ctor_base & operator=(const expected_delete_ctor_base &)=default
expected_delete_ctor_base & operator=(expected_delete_ctor_base &&) noexcept=default
expected_delete_ctor_base & operator=(const expected_delete_ctor_base &)=default
expected_delete_ctor_base(const expected_delete_ctor_base &)=default
expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept=default
expected_move_assign_base & operator=(const expected_move_assign_base &rhs)=default
expected_move_assign_base & operator=(expected_move_assign_base &&rhs) noexcept(std::is_nothrow_move_constructible< T >::value &&std::is_nothrow_move_assignable< T >::value)
expected_move_assign_base(const expected_move_assign_base &rhs)=default
expected_move_assign_base(expected_move_assign_base &&rhs)=default
expected_move_base(expected_move_base &&rhs) noexcept(std::is_nothrow_move_constructible< T >::value)
expected_move_base(const expected_move_base &rhs)=default
expected_move_base & operator=(const expected_move_base &rhs)=default
expected_move_base & operator=(expected_move_base &&rhs)=default
constexpr const unexpected< E > && geterr() const &&
TL_EXPECTED_11_CONSTEXPR unexpected< E > & geterr() &
void construct_error(Args &&...args) noexcept
TL_EXPECTED_11_CONSTEXPR void destroy_val()
TL_EXPECTED_11_CONSTEXPR unexpected< E > && geterr() &&
constexpr const unexpected< E > & geterr() const &
constexpr const unexpected< E > && geterr() const &&
TL_EXPECTED_11_CONSTEXPR T & get() &
void construct(Args &&...args) noexcept
TL_EXPECTED_11_CONSTEXPR void destroy_val()
constexpr const unexpected< E > & geterr() const &
TL_EXPECTED_11_CONSTEXPR T && get() &&
void construct_with(Rhs &&rhs) noexcept
constexpr const T && get() const &&
constexpr const T & get() const &
void construct_error(Args &&...args) noexcept
TL_EXPECTED_11_CONSTEXPR unexpected< E > && geterr() &&
TL_EXPECTED_11_CONSTEXPR unexpected< E > & geterr() &
expected_storage_base(expected_storage_base &&)=default
constexpr expected_storage_base(unexpect_t, std::initializer_list< U > il, Args &&...args)
constexpr expected_storage_base(in_place_t, Args &&...args)
constexpr expected_storage_base(in_place_t, std::initializer_list< U > il, Args &&...args)
expected_storage_base & operator=(const expected_storage_base &)=default
expected_storage_base & operator=(expected_storage_base &&)=default
expected_storage_base(const expected_storage_base &)=default
constexpr expected_storage_base(unexpect_t, Args &&...args)
expected_storage_base & operator=(const expected_storage_base &)=default
expected_storage_base(const expected_storage_base &)=default
constexpr expected_storage_base(unexpect_t, Args &&...args)
expected_storage_base(expected_storage_base &&)=default
constexpr expected_storage_base(unexpect_t, std::initializer_list< U > il, Args &&...args)
constexpr expected_storage_base(in_place_t, std::initializer_list< U > il, Args &&...args)
constexpr expected_storage_base(in_place_t, Args &&...args)
expected_storage_base & operator=(expected_storage_base &&)=default
TL_EXPECTED_MSVC2015_CONSTEXPR expected_storage_base(no_init_t)
expected_storage_base(expected_storage_base &&)=default
expected_storage_base & operator=(const expected_storage_base &)=default
constexpr expected_storage_base(in_place_t, std::initializer_list< U > il, Args &&...args)
constexpr expected_storage_base(unexpect_t, Args &&...args)
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)
constexpr expected_storage_base(in_place_t, Args &&...args)
constexpr expected_storage_base(unexpect_t, std::initializer_list< U > il, Args &&...args)
expected_storage_base & operator=(expected_storage_base &&)=default
expected_storage_base(expected_storage_base &&)=default
expected_storage_base & operator=(const expected_storage_base &)=default
constexpr expected_storage_base(unexpect_t, Args &&...args)
expected_storage_base(const expected_storage_base &)=default
expected_storage_base(expected_storage_base &&)=default
expected_storage_base & operator=(expected_storage_base &&)=default
expected_storage_base(const expected_storage_base &)=default
constexpr expected_storage_base(unexpect_t, std::initializer_list< U > il, Args &&...args)
expected_storage_base & operator=(const expected_storage_base &)=default
constexpr expected_storage_base(unexpect_t, Args &&...args)
constexpr expected_storage_base(unexpect_t, std::initializer_list< U > il, Args &&...args)
constexpr expected_storage_base(in_place_t, std::initializer_list< U > il, Args &&...args)
constexpr expected_storage_base(no_init_t)
constexpr expected_storage_base(in_place_t, Args &&...args)
constexpr expected_storage_base(unexpect_t, Args &&...args)
in_place_t()=default
unexpect_t()=default