1 
2 ///
3 // optional - An implementation of std::optional with extensions
4 // Written in 2017 by Simon Brand (simonrbrand@gmail.com, @TartanLlama)
5 //
6 // Documentation available at https://tl.tartanllama.xyz/
7 //
8 // To the extent possible under law, the author(s) have dedicated all
9 // copyright and related and neighboring rights to this software to the
10 // public domain worldwide. This software is distributed without any warranty.
11 //
12 // You should have received a copy of the CC0 Public Domain Dedication
13 // along with this software. If not, see
14 // <http://creativecommons.org/publicdomain/zero/1.0/>.
15 ///
16 
17 #ifndef TL_OPTIONAL_HPP
18 #define TL_OPTIONAL_HPP
19 
20 #define TL_OPTIONAL_VERSION_MAJOR 1
21 #define TL_OPTIONAL_VERSION_MINOR 0
22 #define TL_OPTIONAL_VERSION_PATCH 0
23 
24 #include <exception>
25 #include <functional>
26 #include <new>
27 #include <type_traits>
28 #include <utility>
29 
30 #if (defined(_MSC_VER) && _MSC_VER == 1900)
31 #define TL_OPTIONAL_MSVC2015
32 #endif
33 
34 #if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 &&              \
35      !defined(__clang__))
36 #define TL_OPTIONAL_GCC49
37 #endif
38 
39 #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 &&              \
40      !defined(__clang__))
41 #define TL_OPTIONAL_GCC54
42 #endif
43 
44 #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 &&              \
45      !defined(__clang__))
46 #define TL_OPTIONAL_GCC55
47 #endif
48 
49 #if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 &&              \
50      !defined(__clang__))
51 // GCC < 5 doesn't support overloading on const&& for member functions
52 #define TL_OPTIONAL_NO_CONSTRR
53 
54 // GCC < 5 doesn't support some standard C++11 type traits
55 #define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)                                     \
56   std::has_trivial_copy_constructor<T>::value
57 #define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign<T>::value
58 
59 // This one will be different for GCC 5.7 if it's ever supported
60 #define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
61 
62 // GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks std::vector
63 // for non-copyable types
64 #elif (defined(__GNUC__) && __GNUC__ < 8 &&                                                \
65      !defined(__clang__))
66 #ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
67 #define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
68 namespace tl {
69   namespace detail {
70       template<class T>
71       struct is_trivially_copy_constructible : std::is_trivially_copy_constructible<T>{};
72 #ifdef _GLIBCXX_VECTOR
73       template<class T, class A>
74       struct is_trivially_copy_constructible<std::vector<T,A>>
75           : std::is_trivially_copy_constructible<T>{};
76 #endif
77   }
78 }
79 #endif
80 
81 #define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)                                     \
82     tl::detail::is_trivially_copy_constructible<T>::value
83 #define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T)                                        \
84   std::is_trivially_copy_assignable<T>::value
85 #define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
86 #else
87 #define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)                                     \
88   std::is_trivially_copy_constructible<T>::value
89 #define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T)                                        \
90   std::is_trivially_copy_assignable<T>::value
91 #define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value
92 #endif
93 
94 #if __cplusplus > 201103L
95 #define TL_OPTIONAL_CXX14
96 #endif
97 
98 // constexpr implies const in C++11, not C++14
99 #if (__cplusplus == 201103L || defined(TL_OPTIONAL_MSVC2015) ||                \
100      defined(TL_OPTIONAL_GCC49))
101 #define TL_OPTIONAL_11_CONSTEXPR
102 #else
103 #define TL_OPTIONAL_11_CONSTEXPR constexpr
104 #endif
105 
106 namespace tl {
107 #ifndef TL_MONOSTATE_INPLACE_MUTEX
108 #define TL_MONOSTATE_INPLACE_MUTEX
109 /// Used to represent an optional with no data; essentially a bool
110 class monostate {};
111 
112 ///  A tag type to tell optional to construct its value in-place
113 struct in_place_t {
114   explicit in_place_t() = default;
115 };
116 /// A tag to tell optional to construct its value in-place
117 static constexpr in_place_t in_place{};
118 #endif
119 
120 template <class T> class optional;
121 
122 namespace detail {
123 #ifndef TL_TRAITS_MUTEX
124 #define TL_TRAITS_MUTEX
125 // C++14-style aliases for brevity
126 template <class T> using remove_const_t = typename std::remove_const<T>::type;
127 template <class T>
128 using remove_reference_t = typename std::remove_reference<T>::type;
129 template <class T> using decay_t = typename std::decay<T>::type;
130 template <bool E, class T = void>
131 using enable_if_t = typename std::enable_if<E, T>::type;
132 template <bool B, class T, class F>
133 using conditional_t = typename std::conditional<B, T, F>::type;
134 
135 // std::conjunction from C++17
136 template <class...> struct conjunction : std::true_type {};
137 template <class B> struct conjunction<B> : B {};
138 template <class B, class... Bs>
139 struct conjunction<B, Bs...>
140     : std::conditional<bool(B::value), conjunction<Bs...>, B>::type {};
141 
142 #if defined(_LIBCPP_VERSION) && __cplusplus == 201103L
143 #define TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
144 #endif
145 
146 // In C++11 mode, there's an issue in libc++'s std::mem_fn
147 // which results in a hard-error when using it in a noexcept expression
148 // in some cases. This is a check to workaround the common failing case.
149 #ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
150 template <class T> struct is_pointer_to_non_const_member_func : std::false_type{};
151 template <class T, class Ret, class... Args>
152 struct is_pointer_to_non_const_member_func<Ret (T::*) (Args...)> : std::true_type{};
153 template <class T, class Ret, class... Args>
154 struct is_pointer_to_non_const_member_func<Ret (T::*) (Args...)&> : std::true_type{};
155 template <class T, class Ret, class... Args>
156 struct is_pointer_to_non_const_member_func<Ret (T::*) (Args...)&&> : std::true_type{};
157 template <class T, class Ret, class... Args>
158 struct is_pointer_to_non_const_member_func<Ret (T::*) (Args...) volatile> : std::true_type{};
159 template <class T, class Ret, class... Args>
160 struct is_pointer_to_non_const_member_func<Ret (T::*) (Args...) volatile&> : std::true_type{};
161 template <class T, class Ret, class... Args>
162 struct is_pointer_to_non_const_member_func<Ret (T::*) (Args...) volatile&&> : std::true_type{};
163 
164 template <class T> struct is_const_or_const_ref : std::false_type{};
165 template <class T> struct is_const_or_const_ref<T const&> : std::true_type{};
166 template <class T> struct is_const_or_const_ref<T const> : std::true_type{};
167 #endif
168 
169 // std::invoke from C++17
170 // https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround
171 template <typename Fn, typename... Args,
172 #ifdef TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
173           typename = enable_if_t<!(is_pointer_to_non_const_member_func<Fn>::value
174                                  && is_const_or_const_ref<Args...>::value)>,
175 #endif
176           typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>,
177           int = 0>
invoke(Fn && f,Args &&...args)178 constexpr auto invoke(Fn &&f, Args &&... args) noexcept(
179     noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))
180     -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) {
181   return std::mem_fn(f)(std::forward<Args>(args)...);
182 }
183 
184 template <typename Fn, typename... Args,
185           typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>::value>>
invoke(Fn && f,Args &&...args)186 constexpr auto invoke(Fn &&f, Args &&... args) noexcept(
187     noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))
188     -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) {
189   return std::forward<Fn>(f)(std::forward<Args>(args)...);
190 }
191 
192 // std::invoke_result from C++17
193 template <class F, class, class... Us> struct invoke_result_impl;
194 
195 template <class F, class... Us>
196 struct invoke_result_impl<
197     F, decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...), void()),
198     Us...> {
199   using type = decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...));
200 };
201 
202 template <class F, class... Us>
203 using invoke_result = invoke_result_impl<F, void, Us...>;
204 
205 template <class F, class... Us>
206 using invoke_result_t = typename invoke_result<F, Us...>::type;
207 
208 #if defined(_MSC_VER) && _MSC_VER <= 1900
209 // TODO make a version which works with MSVC 2015
210 template <class T, class U = T> struct is_swappable : std::true_type {};
211 
212 template <class T, class U = T> struct is_nothrow_swappable : std::true_type {};
213 #else
214 // https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept
215 namespace swap_adl_tests {
216 // if swap ADL finds this then it would call std::swap otherwise (same
217 // signature)
218 struct tag {};
219 
220 template <class T> tag swap(T &, T &);
221 template <class T, std::size_t N> tag swap(T (&a)[N], T (&b)[N]);
222 
223 // helper functions to test if an unqualified swap is possible, and if it
224 // becomes std::swap
225 template <class, class> std::false_type can_swap(...) noexcept(false);
226 template <class T, class U,
227           class = decltype(swap(std::declval<T &>(), std::declval<U &>()))>
228 std::true_type can_swap(int) noexcept(noexcept(swap(std::declval<T &>(),
229                                                     std::declval<U &>())));
230 
231 template <class, class> std::false_type uses_std(...);
232 template <class T, class U>
233 std::is_same<decltype(swap(std::declval<T &>(), std::declval<U &>())), tag>
234 uses_std(int);
235 
236 template <class T>
237 struct is_std_swap_noexcept
238     : std::integral_constant<bool,
239                              std::is_nothrow_move_constructible<T>::value &&
240                                  std::is_nothrow_move_assignable<T>::value> {};
241 
242 template <class T, std::size_t N>
243 struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> {};
244 
245 template <class T, class U>
246 struct is_adl_swap_noexcept
247     : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};
248 } // namespace swap_adl_tests
249 
250 template <class T, class U = T>
251 struct is_swappable
252     : std::integral_constant<
253           bool,
254           decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&
255               (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||
256                (std::is_move_assignable<T>::value &&
257                 std::is_move_constructible<T>::value))> {};
258 
259 template <class T, std::size_t N>
260 struct is_swappable<T[N], T[N]>
261     : std::integral_constant<
262           bool,
263           decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&
264               (!decltype(
265                    detail::swap_adl_tests::uses_std<T[N], T[N]>(0))::value ||
266                is_swappable<T, T>::value)> {};
267 
268 template <class T, class U = T>
269 struct is_nothrow_swappable
270     : std::integral_constant<
271           bool,
272           is_swappable<T, U>::value &&
273               ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value
274                     &&detail::swap_adl_tests::is_std_swap_noexcept<T>::value) ||
275                (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
276                     detail::swap_adl_tests::is_adl_swap_noexcept<T,
277                                                                  U>::value))> {
278 };
279 #endif
280 #endif
281 
282 // std::void_t from C++17
283 template <class...> struct voider { using type = void; };
284 template <class... Ts> using void_t = typename voider<Ts...>::type;
285 
286 // Trait for checking if a type is a tl::optional
287 template <class T> struct is_optional_impl : std::false_type {};
288 template <class T> struct is_optional_impl<optional<T>> : std::true_type {};
289 template <class T> using is_optional = is_optional_impl<decay_t<T>>;
290 
291 // Change void to tl::monostate
292 template <class U>
293 using fixup_void = conditional_t<std::is_void<U>::value, monostate, U>;
294 
295 template <class F, class U, class = invoke_result_t<F, U>>
296 using get_map_return = optional<fixup_void<invoke_result_t<F, U>>>;
297 
298 // Check if invoking F for some Us returns void
299 template <class F, class = void, class... U> struct returns_void_impl;
300 template <class F, class... U>
301 struct returns_void_impl<F, void_t<invoke_result_t<F, U...>>, U...>
302     : std::is_void<invoke_result_t<F, U...>> {};
303 template <class F, class... U>
304 using returns_void = returns_void_impl<F, void, U...>;
305 
306 template <class T, class... U>
307 using enable_if_ret_void = enable_if_t<returns_void<T &&, U...>::value>;
308 
309 template <class T, class... U>
310 using disable_if_ret_void = enable_if_t<!returns_void<T &&, U...>::value>;
311 
312 template <class T, class U>
313 using enable_forward_value =
314     detail::enable_if_t<std::is_constructible<T, U &&>::value &&
315                         !std::is_same<detail::decay_t<U>, in_place_t>::value &&
316                         !std::is_same<optional<T>, detail::decay_t<U>>::value>;
317 
318 template <class T, class U, class Other>
319 using enable_from_other = detail::enable_if_t<
320     std::is_constructible<T, Other>::value &&
321     !std::is_constructible<T, optional<U> &>::value &&
322     !std::is_constructible<T, optional<U> &&>::value &&
323     !std::is_constructible<T, const optional<U> &>::value &&
324     !std::is_constructible<T, const optional<U> &&>::value &&
325     !std::is_convertible<optional<U> &, T>::value &&
326     !std::is_convertible<optional<U> &&, T>::value &&
327     !std::is_convertible<const optional<U> &, T>::value &&
328     !std::is_convertible<const optional<U> &&, T>::value>;
329 
330 template <class T, class U>
331 using enable_assign_forward = detail::enable_if_t<
332     !std::is_same<optional<T>, detail::decay_t<U>>::value &&
333     !detail::conjunction<std::is_scalar<T>,
334                          std::is_same<T, detail::decay_t<U>>>::value &&
335     std::is_constructible<T, U>::value && std::is_assignable<T &, U>::value>;
336 
337 template <class T, class U, class Other>
338 using enable_assign_from_other = detail::enable_if_t<
339     std::is_constructible<T, Other>::value &&
340     std::is_assignable<T &, Other>::value &&
341     !std::is_constructible<T, optional<U> &>::value &&
342     !std::is_constructible<T, optional<U> &&>::value &&
343     !std::is_constructible<T, const optional<U> &>::value &&
344     !std::is_constructible<T, const optional<U> &&>::value &&
345     !std::is_convertible<optional<U> &, T>::value &&
346     !std::is_convertible<optional<U> &&, T>::value &&
347     !std::is_convertible<const optional<U> &, T>::value &&
348     !std::is_convertible<const optional<U> &&, T>::value &&
349     !std::is_assignable<T &, optional<U> &>::value &&
350     !std::is_assignable<T &, optional<U> &&>::value &&
351     !std::is_assignable<T &, const optional<U> &>::value &&
352     !std::is_assignable<T &, const optional<U> &&>::value>;
353 
354 // The storage base manages the actual storage, and correctly propagates
355 // trivial destruction from T. This case is for when T is not trivially
356 // destructible.
357 template <class T, bool = ::std::is_trivially_destructible<T>::value>
358 struct optional_storage_base {
optional_storage_basetl::detail::optional_storage_base359   TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
360       : m_dummy(), m_has_value(false) {}
361 
362   template <class... U>
optional_storage_basetl::detail::optional_storage_base363   TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u)
364       : m_value(std::forward<U>(u)...), m_has_value(true) {}
365 
~optional_storage_basetl::detail::optional_storage_base366   ~optional_storage_base() {
367     if (m_has_value) {
368       m_value.~T();
369       m_has_value = false;
370     }
371   }
372 
373   struct dummy {};
374   union {
375     dummy m_dummy;
376     T m_value;
377   };
378 
379   bool m_has_value;
380 };
381 
382 // This case is for when T is trivially destructible.
383 template <class T> struct optional_storage_base<T, true> {
optional_storage_basetl::detail::optional_storage_base384   TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
385       : m_dummy(), m_has_value(false) {}
386 
387   template <class... U>
optional_storage_basetl::detail::optional_storage_base388   TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u)
389       : m_value(std::forward<U>(u)...), m_has_value(true) {}
390 
391   // No destructor, so this class is trivially destructible
392 
393   struct dummy {};
394   union {
395     dummy m_dummy;
396     T m_value;
397   };
398 
399   bool m_has_value = false;
400 };
401 
402 // This base class provides some handy member functions which can be used in
403 // further derived classes
404 template <class T> struct optional_operations_base : optional_storage_base<T> {
405   using optional_storage_base<T>::optional_storage_base;
406 
hard_resettl::detail::optional_operations_base407   void hard_reset() noexcept {
408     get().~T();
409     this->m_has_value = false;
410   }
411 
constructtl::detail::optional_operations_base412   template <class... Args> void construct(Args &&... args) noexcept {
413     new (std::addressof(this->m_value)) T(std::forward<Args>(args)...);
414     this->m_has_value = true;
415   }
416 
assigntl::detail::optional_operations_base417   template <class Opt> void assign(Opt &&rhs) {
418     if (this->has_value()) {
419       if (rhs.has_value()) {
420         this->m_value = std::forward<Opt>(rhs).get();
421       } else {
422         this->m_value.~T();
423         this->m_has_value = false;
424       }
425     }
426 
427     else if (rhs.has_value()) {
428       construct(std::forward<Opt>(rhs).get());
429     }
430   }
431 
has_valuetl::detail::optional_operations_base432   bool has_value() const { return this->m_has_value; }
433 
gettl::detail::optional_operations_base434   TL_OPTIONAL_11_CONSTEXPR T &get() & { return this->m_value; }
gettl::detail::optional_operations_base435   TL_OPTIONAL_11_CONSTEXPR const T &get() const & { return this->m_value; }
gettl::detail::optional_operations_base436   TL_OPTIONAL_11_CONSTEXPR T &&get() && { return std::move(this->m_value); }
437 #ifndef TL_OPTIONAL_NO_CONSTRR
gettl::detail::optional_operations_base438   constexpr const T &&get() const && { return std::move(this->m_value); }
439 #endif
440 };
441 
442 // This class manages conditionally having a trivial copy constructor
443 // This specialization is for when T is trivially copy constructible
444 template <class T, bool = TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>
445 struct optional_copy_base : optional_operations_base<T> {
446   using optional_operations_base<T>::optional_operations_base;
447 };
448 
449 // This specialization is for when T is not trivially copy constructible
450 template <class T>
451 struct optional_copy_base<T, false> : optional_operations_base<T> {
452   using optional_operations_base<T>::optional_operations_base;
453 
454   optional_copy_base() = default;
optional_copy_basetl::detail::optional_copy_base455   optional_copy_base(const optional_copy_base &rhs) {
456     if (rhs.has_value()) {
457       this->construct(rhs.get());
458     } else {
459       this->m_has_value = false;
460     }
461   }
462 
463   optional_copy_base(optional_copy_base &&rhs) = default;
464   optional_copy_base &operator=(const optional_copy_base &rhs) = default;
465   optional_copy_base &operator=(optional_copy_base &&rhs) = default;
466 };
467 
468 // This class manages conditionally having a trivial move constructor
469 // Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
470 // doesn't implement an analogue to std::is_trivially_move_constructible. We
471 // have to make do with a non-trivial move constructor even if T is trivially
472 // move constructible
473 #ifndef TL_OPTIONAL_GCC49
474 template <class T, bool = std::is_trivially_move_constructible<T>::value>
475 struct optional_move_base : optional_copy_base<T> {
476   using optional_copy_base<T>::optional_copy_base;
477 };
478 #else
479 template <class T, bool = false> struct optional_move_base;
480 #endif
481 template <class T> struct optional_move_base<T, false> : optional_copy_base<T> {
482   using optional_copy_base<T>::optional_copy_base;
483 
484   optional_move_base() = default;
485   optional_move_base(const optional_move_base &rhs) = default;
486 
optional_move_basetl::detail::optional_move_base487   optional_move_base(optional_move_base &&rhs) noexcept(
488       std::is_nothrow_move_constructible<T>::value) {
489     if (rhs.has_value()) {
490       this->construct(std::move(rhs.get()));
491     } else {
492       this->m_has_value = false;
493     }
494   }
495   optional_move_base &operator=(const optional_move_base &rhs) = default;
496   optional_move_base &operator=(optional_move_base &&rhs) = default;
497 };
498 
499 // This class manages conditionally having a trivial copy assignment operator
500 template <class T, bool = TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) &&
501                           TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) &&
502                           TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T)>
503 struct optional_copy_assign_base : optional_move_base<T> {
504   using optional_move_base<T>::optional_move_base;
505 };
506 
507 template <class T>
508 struct optional_copy_assign_base<T, false> : optional_move_base<T> {
509   using optional_move_base<T>::optional_move_base;
510 
511   optional_copy_assign_base() = default;
512   optional_copy_assign_base(const optional_copy_assign_base &rhs) = default;
513 
514   optional_copy_assign_base(optional_copy_assign_base &&rhs) = default;
operator =tl::detail::optional_copy_assign_base515   optional_copy_assign_base &operator=(const optional_copy_assign_base &rhs) {
516     this->assign(rhs);
517     return *this;
518   }
519   optional_copy_assign_base &
520   operator=(optional_copy_assign_base &&rhs) = default;
521 };
522 
523 // This class manages conditionally having a trivial move assignment operator
524 // Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
525 // doesn't implement an analogue to std::is_trivially_move_assignable. We have
526 // to make do with a non-trivial move assignment operator even if T is trivially
527 // move assignable
528 #ifndef TL_OPTIONAL_GCC49
529 template <class T, bool = std::is_trivially_destructible<T>::value
530                        &&std::is_trivially_move_constructible<T>::value
531                            &&std::is_trivially_move_assignable<T>::value>
532 struct optional_move_assign_base : optional_copy_assign_base<T> {
533   using optional_copy_assign_base<T>::optional_copy_assign_base;
534 };
535 #else
536 template <class T, bool = false> struct optional_move_assign_base;
537 #endif
538 
539 template <class T>
540 struct optional_move_assign_base<T, false> : optional_copy_assign_base<T> {
541   using optional_copy_assign_base<T>::optional_copy_assign_base;
542 
543   optional_move_assign_base() = default;
544   optional_move_assign_base(const optional_move_assign_base &rhs) = default;
545 
546   optional_move_assign_base(optional_move_assign_base &&rhs) = default;
547 
548   optional_move_assign_base &
549   operator=(const optional_move_assign_base &rhs) = default;
550 
551   optional_move_assign_base &
operator =tl::detail::optional_move_assign_base552   operator=(optional_move_assign_base &&rhs) noexcept(
553       std::is_nothrow_move_constructible<T>::value
554           &&std::is_nothrow_move_assignable<T>::value) {
555     this->assign(std::move(rhs));
556     return *this;
557   }
558 };
559 
560 // optional_delete_ctor_base will conditionally delete copy and move
561 // constructors depending on whether T is copy/move constructible
562 template <class T, bool EnableCopy = std::is_copy_constructible<T>::value,
563           bool EnableMove = std::is_move_constructible<T>::value>
564 struct optional_delete_ctor_base {
565   optional_delete_ctor_base() = default;
566   optional_delete_ctor_base(const optional_delete_ctor_base &) = default;
567   optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = default;
568   optional_delete_ctor_base &
569   operator=(const optional_delete_ctor_base &) = default;
570   optional_delete_ctor_base &
571   operator=(optional_delete_ctor_base &&) noexcept = default;
572 };
573 
574 template <class T> struct optional_delete_ctor_base<T, true, false> {
575   optional_delete_ctor_base() = default;
576   optional_delete_ctor_base(const optional_delete_ctor_base &) = default;
577   optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = delete;
578   optional_delete_ctor_base &
579   operator=(const optional_delete_ctor_base &) = default;
580   optional_delete_ctor_base &
581   operator=(optional_delete_ctor_base &&) noexcept = default;
582 };
583 
584 template <class T> struct optional_delete_ctor_base<T, false, true> {
585   optional_delete_ctor_base() = default;
586   optional_delete_ctor_base(const optional_delete_ctor_base &) = delete;
587   optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = default;
588   optional_delete_ctor_base &
589   operator=(const optional_delete_ctor_base &) = default;
590   optional_delete_ctor_base &
591   operator=(optional_delete_ctor_base &&) noexcept = default;
592 };
593 
594 template <class T> struct optional_delete_ctor_base<T, false, false> {
595   optional_delete_ctor_base() = default;
596   optional_delete_ctor_base(const optional_delete_ctor_base &) = delete;
597   optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = delete;
598   optional_delete_ctor_base &
599   operator=(const optional_delete_ctor_base &) = default;
600   optional_delete_ctor_base &
601   operator=(optional_delete_ctor_base &&) noexcept = default;
602 };
603 
604 // optional_delete_assign_base will conditionally delete copy and move
605 // constructors depending on whether T is copy/move constructible + assignable
606 template <class T,
607           bool EnableCopy = (std::is_copy_constructible<T>::value &&
608                              std::is_copy_assignable<T>::value),
609           bool EnableMove = (std::is_move_constructible<T>::value &&
610                              std::is_move_assignable<T>::value)>
611 struct optional_delete_assign_base {
612   optional_delete_assign_base() = default;
613   optional_delete_assign_base(const optional_delete_assign_base &) = default;
614   optional_delete_assign_base(optional_delete_assign_base &&) noexcept =
615       default;
616   optional_delete_assign_base &
617   operator=(const optional_delete_assign_base &) = default;
618   optional_delete_assign_base &
619   operator=(optional_delete_assign_base &&) noexcept = default;
620 };
621 
622 template <class T> struct optional_delete_assign_base<T, true, false> {
623   optional_delete_assign_base() = default;
624   optional_delete_assign_base(const optional_delete_assign_base &) = default;
625   optional_delete_assign_base(optional_delete_assign_base &&) noexcept =
626       default;
627   optional_delete_assign_base &
628   operator=(const optional_delete_assign_base &) = default;
629   optional_delete_assign_base &
630   operator=(optional_delete_assign_base &&) noexcept = delete;
631 };
632 
633 template <class T> struct optional_delete_assign_base<T, false, true> {
634   optional_delete_assign_base() = default;
635   optional_delete_assign_base(const optional_delete_assign_base &) = default;
636   optional_delete_assign_base(optional_delete_assign_base &&) noexcept =
637       default;
638   optional_delete_assign_base &
639   operator=(const optional_delete_assign_base &) = delete;
640   optional_delete_assign_base &
641   operator=(optional_delete_assign_base &&) noexcept = default;
642 };
643 
644 template <class T> struct optional_delete_assign_base<T, false, false> {
645   optional_delete_assign_base() = default;
646   optional_delete_assign_base(const optional_delete_assign_base &) = default;
647   optional_delete_assign_base(optional_delete_assign_base &&) noexcept =
648       default;
649   optional_delete_assign_base &
650   operator=(const optional_delete_assign_base &) = delete;
651   optional_delete_assign_base &
652   operator=(optional_delete_assign_base &&) noexcept = delete;
653 };
654 
655 } // namespace detail
656 
657 /// A tag type to represent an empty optional
658 struct nullopt_t {
659   struct do_not_use {};
nullopt_ttl::nullopt_t660   constexpr explicit nullopt_t(do_not_use, do_not_use) noexcept {}
661 };
662 /// Represents an empty optional
663 static constexpr nullopt_t nullopt{nullopt_t::do_not_use{},
664                                    nullopt_t::do_not_use{}};
665 
666 class bad_optional_access : public std::exception {
667 public:
668   bad_optional_access() = default;
what() const669   const char *what() const noexcept { return "Optional has no value"; }
670 };
671 
672 /// An optional object is an object that contains the storage for another
673 /// object and manages the lifetime of this contained object, if any. The
674 /// contained object may be initialized after the optional object has been
675 /// initialized, and may be destroyed before the optional object has been
676 /// destroyed. The initialization state of the contained object is tracked by
677 /// the optional object.
678 template <class T>
679 class optional : private detail::optional_move_assign_base<T>,
680                  private detail::optional_delete_ctor_base<T>,
681                  private detail::optional_delete_assign_base<T> {
682   using base = detail::optional_move_assign_base<T>;
683 
684   static_assert(!std::is_same<T, in_place_t>::value,
685                 "instantiation of optional with in_place_t is ill-formed");
686   static_assert(!std::is_same<detail::decay_t<T>, nullopt_t>::value,
687                 "instantiation of optional with nullopt_t is ill-formed");
688 
689 public:
690 // The different versions for C++14 and 11 are needed because deduced return
691 // types are not SFINAE-safe. This provides better support for things like
692 // generic lambdas. C.f.
693 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html
694 #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \
695     !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
696   /// Carries out some operation which returns an optional on the stored
697   /// object if there is one.
and_then(F && f)698   template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) & {
699     using result = detail::invoke_result_t<F, T &>;
700     static_assert(detail::is_optional<result>::value,
701                   "F must return an optional");
702 
703     return has_value() ? detail::invoke(std::forward<F>(f), **this)
704                        : result(nullopt);
705   }
706 
and_then(F && f)707   template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) && {
708     using result = detail::invoke_result_t<F, T &&>;
709     static_assert(detail::is_optional<result>::value,
710                   "F must return an optional");
711 
712     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
713                        : result(nullopt);
714   }
715 
and_then(F && f) const716   template <class F> constexpr auto and_then(F &&f) const & {
717     using result = detail::invoke_result_t<F, const T &>;
718     static_assert(detail::is_optional<result>::value,
719                   "F must return an optional");
720 
721     return has_value() ? detail::invoke(std::forward<F>(f), **this)
722                        : result(nullopt);
723   }
724 
725 #ifndef TL_OPTIONAL_NO_CONSTRR
and_then(F && f) const726   template <class F> constexpr auto and_then(F &&f) const && {
727     using result = detail::invoke_result_t<F, const T &&>;
728     static_assert(detail::is_optional<result>::value,
729                   "F must return an optional");
730 
731     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
732                        : result(nullopt);
733   }
734 #endif
735 #else
736   /// Carries out some operation which returns an optional on the stored
737   /// object if there is one.
738   template <class F>
739   TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) & {
740     using result = detail::invoke_result_t<F, T &>;
741     static_assert(detail::is_optional<result>::value,
742                   "F must return an optional");
743 
744     return has_value() ? detail::invoke(std::forward<F>(f), **this)
745                        : result(nullopt);
746   }
747 
748   template <class F>
749   TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &&> and_then(F &&f) && {
750     using result = detail::invoke_result_t<F, T &&>;
751     static_assert(detail::is_optional<result>::value,
752                   "F must return an optional");
753 
754     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
755                        : result(nullopt);
756   }
757 
758   template <class F>
759   constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const & {
760     using result = detail::invoke_result_t<F, const T &>;
761     static_assert(detail::is_optional<result>::value,
762                   "F must return an optional");
763 
764     return has_value() ? detail::invoke(std::forward<F>(f), **this)
765                        : result(nullopt);
766   }
767 
768 #ifndef TL_OPTIONAL_NO_CONSTRR
769   template <class F>
770   constexpr detail::invoke_result_t<F, const T &&> and_then(F &&f) const && {
771     using result = detail::invoke_result_t<F, const T &&>;
772     static_assert(detail::is_optional<result>::value,
773                   "F must return an optional");
774 
775     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
776                        : result(nullopt);
777   }
778 #endif
779 #endif
780 
781 #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \
782     !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
783   /// Carries out some operation on the stored object if there is one.
map(F && f)784   template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) & {
785     return optional_map_impl(*this, std::forward<F>(f));
786   }
787 
map(F && f)788   template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) && {
789     return optional_map_impl(std::move(*this), std::forward<F>(f));
790   }
791 
map(F && f) const792   template <class F> constexpr auto map(F &&f) const & {
793     return optional_map_impl(*this, std::forward<F>(f));
794   }
795 
map(F && f) const796   template <class F> constexpr auto map(F &&f) const && {
797     return optional_map_impl(std::move(*this), std::forward<F>(f));
798   }
799 #else
800   /// Carries out some operation on the stored object if there is one.
801   template <class F>
optional_map_impl(std::declval<optional &> (),std::declval<F &&> ())802   TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional &>(),
803                                              std::declval<F &&>()))
804   map(F &&f) & {
805     return optional_map_impl(*this, std::forward<F>(f));
806   }
807 
808   template <class F>
optional_map_impl(std::declval<optional &&> (),std::declval<F &&> ())809   TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional &&>(),
810                                              std::declval<F &&>()))
811   map(F &&f) && {
812     return optional_map_impl(std::move(*this), std::forward<F>(f));
813   }
814 
815   template <class F>
optional_map_impl(std::declval<const optional &> (),std::declval<F &&> ())816   constexpr decltype(optional_map_impl(std::declval<const optional &>(),
817                               std::declval<F &&>()))
818   map(F &&f) const & {
819     return optional_map_impl(*this, std::forward<F>(f));
820   }
821 
822 #ifndef TL_OPTIONAL_NO_CONSTRR
823   template <class F>
optional_map_impl(std::declval<const optional &&> (),std::declval<F &&> ())824   constexpr decltype(optional_map_impl(std::declval<const optional &&>(),
825                               std::declval<F &&>()))
826   map(F &&f) const && {
827     return optional_map_impl(std::move(*this), std::forward<F>(f));
828   }
829 #endif
830 #endif
831 
832 #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \
833     !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
834   /// Carries out some operation on the stored object if there is one.
transform(F && f)835   template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) & {
836     return optional_map_impl(*this, std::forward<F>(f));
837   }
838 
transform(F && f)839   template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) && {
840     return optional_map_impl(std::move(*this), std::forward<F>(f));
841   }
842 
transform(F && f) const843   template <class F> constexpr auto transform(F&& f) const & {
844     return optional_map_impl(*this, std::forward<F>(f));
845   }
846 
transform(F && f) const847   template <class F> constexpr auto transform(F&& f) const && {
848     return optional_map_impl(std::move(*this), std::forward<F>(f));
849   }
850 #else
851   /// Carries out some operation on the stored object if there is one.
852   template <class F>
optional_map_impl(std::declval<optional &> (),std::declval<F &&> ())853   TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&>(),
854     std::declval<F&&>()))
855     transform(F&& f) & {
856     return optional_map_impl(*this, std::forward<F>(f));
857   }
858 
859   template <class F>
optional_map_impl(std::declval<optional &&> (),std::declval<F &&> ())860   TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&&>(),
861     std::declval<F&&>()))
862     transform(F&& f) && {
863     return optional_map_impl(std::move(*this), std::forward<F>(f));
864   }
865 
866   template <class F>
optional_map_impl(std::declval<const optional &> (),std::declval<F &&> ())867   constexpr decltype(optional_map_impl(std::declval<const optional&>(),
868     std::declval<F&&>()))
869     transform(F&& f) const & {
870     return optional_map_impl(*this, std::forward<F>(f));
871   }
872 
873 #ifndef TL_OPTIONAL_NO_CONSTRR
874   template <class F>
optional_map_impl(std::declval<const optional &&> (),std::declval<F &&> ())875   constexpr decltype(optional_map_impl(std::declval<const optional&&>(),
876     std::declval<F&&>()))
877     transform(F&& f) const && {
878     return optional_map_impl(std::move(*this), std::forward<F>(f));
879   }
880 #endif
881 #endif
882 
883   /// Calls `f` if the optional is empty
884   template <class F, detail::enable_if_ret_void<F> * = nullptr>
or_else(F && f)885   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {
886     if (has_value())
887       return *this;
888 
889     std::forward<F>(f)();
890     return nullopt;
891   }
892 
893   template <class F, detail::disable_if_ret_void<F> * = nullptr>
or_else(F && f)894   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {
895     return has_value() ? *this : std::forward<F>(f)();
896   }
897 
898   template <class F, detail::enable_if_ret_void<F> * = nullptr>
or_else(F && f)899   optional<T> or_else(F &&f) && {
900     if (has_value())
901       return std::move(*this);
902 
903     std::forward<F>(f)();
904     return nullopt;
905   }
906 
907   template <class F, detail::disable_if_ret_void<F> * = nullptr>
or_else(F && f)908   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) && {
909     return has_value() ? std::move(*this) : std::forward<F>(f)();
910   }
911 
912   template <class F, detail::enable_if_ret_void<F> * = nullptr>
or_else(F && f) const913   optional<T> or_else(F &&f) const & {
914     if (has_value())
915       return *this;
916 
917     std::forward<F>(f)();
918     return nullopt;
919   }
920 
921   template <class F, detail::disable_if_ret_void<F> * = nullptr>
or_else(F && f) const922   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) const & {
923     return has_value() ? *this : std::forward<F>(f)();
924   }
925 
926 #ifndef TL_OPTIONAL_NO_CONSTRR
927   template <class F, detail::enable_if_ret_void<F> * = nullptr>
or_else(F && f) const928   optional<T> or_else(F &&f) const && {
929     if (has_value())
930       return std::move(*this);
931 
932     std::forward<F>(f)();
933     return nullopt;
934   }
935 
936   template <class F, detail::disable_if_ret_void<F> * = nullptr>
or_else(F && f) const937   optional<T> or_else(F &&f) const && {
938     return has_value() ? std::move(*this) : std::forward<F>(f)();
939   }
940 #endif
941 
942   /// Maps the stored value with `f` if there is one, otherwise returns `u`.
map_or(F && f,U && u)943   template <class F, class U> U map_or(F &&f, U &&u) & {
944     return has_value() ? detail::invoke(std::forward<F>(f), **this)
945                        : std::forward<U>(u);
946   }
947 
map_or(F && f,U && u)948   template <class F, class U> U map_or(F &&f, U &&u) && {
949     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
950                        : std::forward<U>(u);
951   }
952 
map_or(F && f,U && u) const953   template <class F, class U> U map_or(F &&f, U &&u) const & {
954     return has_value() ? detail::invoke(std::forward<F>(f), **this)
955                        : std::forward<U>(u);
956   }
957 
958 #ifndef TL_OPTIONAL_NO_CONSTRR
map_or(F && f,U && u) const959   template <class F, class U> U map_or(F &&f, U &&u) const && {
960     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
961                        : std::forward<U>(u);
962   }
963 #endif
964 
965   /// Maps the stored value with `f` if there is one, otherwise calls
966   /// `u` and returns the result.
967   template <class F, class U>
map_or_else(F && f,U && u)968   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) & {
969     return has_value() ? detail::invoke(std::forward<F>(f), **this)
970                        : std::forward<U>(u)();
971   }
972 
973   template <class F, class U>
map_or_else(F && f,U && u)974   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) && {
975     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
976                        : std::forward<U>(u)();
977   }
978 
979   template <class F, class U>
map_or_else(F && f,U && u) const980   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const & {
981     return has_value() ? detail::invoke(std::forward<F>(f), **this)
982                        : std::forward<U>(u)();
983   }
984 
985 #ifndef TL_OPTIONAL_NO_CONSTRR
986   template <class F, class U>
map_or_else(F && f,U && u) const987   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const && {
988     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
989                        : std::forward<U>(u)();
990   }
991 #endif
992 
993   /// Returns `u` if `*this` has a value, otherwise an empty optional.
994   template <class U>
conjunction(U && u) const995   constexpr optional<typename std::decay<U>::type> conjunction(U &&u) const {
996     using result = optional<detail::decay_t<U>>;
997     return has_value() ? result{u} : result{nullopt};
998   }
999 
1000   /// Returns `rhs` if `*this` is empty, otherwise the current value.
disjunction(const optional & rhs)1001   TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) & {
1002     return has_value() ? *this : rhs;
1003   }
1004 
disjunction(const optional & rhs) const1005   constexpr optional disjunction(const optional &rhs) const & {
1006     return has_value() ? *this : rhs;
1007   }
1008 
disjunction(const optional & rhs)1009   TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) && {
1010     return has_value() ? std::move(*this) : rhs;
1011   }
1012 
1013 #ifndef TL_OPTIONAL_NO_CONSTRR
disjunction(const optional & rhs) const1014   constexpr optional disjunction(const optional &rhs) const && {
1015     return has_value() ? std::move(*this) : rhs;
1016   }
1017 #endif
1018 
disjunction(optional && rhs)1019   TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) & {
1020     return has_value() ? *this : std::move(rhs);
1021   }
1022 
disjunction(optional && rhs) const1023   constexpr optional disjunction(optional &&rhs) const & {
1024     return has_value() ? *this : std::move(rhs);
1025   }
1026 
disjunction(optional && rhs)1027   TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) && {
1028     return has_value() ? std::move(*this) : std::move(rhs);
1029   }
1030 
1031 #ifndef TL_OPTIONAL_NO_CONSTRR
disjunction(optional && rhs) const1032   constexpr optional disjunction(optional &&rhs) const && {
1033     return has_value() ? std::move(*this) : std::move(rhs);
1034   }
1035 #endif
1036 
1037   /// Takes the value out of the optional, leaving it empty
take()1038   optional take() {
1039     optional ret = std::move(*this);
1040     reset();
1041     return ret;
1042   }
1043 
1044   using value_type = T;
1045 
1046   /// Constructs an optional that does not contain a value.
1047   constexpr optional() noexcept = default;
1048 
optional(nullopt_t)1049   constexpr optional(nullopt_t) noexcept {}
1050 
1051   /// Copy constructor
1052   ///
1053   /// If `rhs` contains a value, the stored value is direct-initialized with
1054   /// it. Otherwise, the constructed optional is empty.
1055   TL_OPTIONAL_11_CONSTEXPR optional(const optional &rhs) = default;
1056 
1057   /// Move constructor
1058   ///
1059   /// If `rhs` contains a value, the stored value is direct-initialized with
1060   /// it. Otherwise, the constructed optional is empty.
1061   TL_OPTIONAL_11_CONSTEXPR optional(optional &&rhs) = default;
1062 
1063   /// Constructs the stored value in-place using the given arguments.
1064  template <class... Args>
optional(detail::enable_if_t<std::is_constructible<T,Args...>::value,in_place_t>,Args &&...args)1065   constexpr explicit optional(
1066       detail::enable_if_t<std::is_constructible<T, Args...>::value, in_place_t>,
1067       Args &&... args)
1068       : base(in_place, std::forward<Args>(args)...) {}
1069 
1070   template <class U, class... Args>
optional(detail::enable_if_t<std::is_constructible<T,std::initializer_list<U> &,Args &&...>::value,in_place_t>,std::initializer_list<U> il,Args &&...args)1071   TL_OPTIONAL_11_CONSTEXPR explicit optional(
1072       detail::enable_if_t<std::is_constructible<T, std::initializer_list<U> &,
1073                                                 Args &&...>::value,
1074                           in_place_t>,
1075       std::initializer_list<U> il, Args &&... args) {
1076     this->construct(il, std::forward<Args>(args)...);
1077   }
1078 
1079   /// Constructs the stored value with `u`.
1080   template <
1081       class U = T,
1082       detail::enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr,
1083       detail::enable_forward_value<T, U> * = nullptr>
optional(U && u)1084   constexpr optional(U &&u) : base(in_place, std::forward<U>(u)) {}
1085 
1086   template <
1087       class U = T,
1088       detail::enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr,
1089       detail::enable_forward_value<T, U> * = nullptr>
optional(U && u)1090   constexpr explicit optional(U &&u) : base(in_place, std::forward<U>(u)) {}
1091 
1092   /// Converting copy constructor.
1093   template <
1094       class U, detail::enable_from_other<T, U, const U &> * = nullptr,
1095       detail::enable_if_t<std::is_convertible<const U &, T>::value> * = nullptr>
optional(const optional<U> & rhs)1096   optional(const optional<U> &rhs) {
1097     if (rhs.has_value()) {
1098       this->construct(*rhs);
1099     }
1100   }
1101 
1102   template <class U, detail::enable_from_other<T, U, const U &> * = nullptr,
1103             detail::enable_if_t<!std::is_convertible<const U &, T>::value> * =
1104                 nullptr>
optional(const optional<U> & rhs)1105   explicit optional(const optional<U> &rhs) {
1106     if (rhs.has_value()) {
1107       this->construct(*rhs);
1108     }
1109   }
1110 
1111   /// Converting move constructor.
1112   template <
1113       class U, detail::enable_from_other<T, U, U &&> * = nullptr,
1114       detail::enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr>
optional(optional<U> && rhs)1115   optional(optional<U> &&rhs) {
1116     if (rhs.has_value()) {
1117       this->construct(std::move(*rhs));
1118     }
1119   }
1120 
1121   template <
1122       class U, detail::enable_from_other<T, U, U &&> * = nullptr,
1123       detail::enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr>
optional(optional<U> && rhs)1124   explicit optional(optional<U> &&rhs) {
1125     if (rhs.has_value()) {
1126       this->construct(std::move(*rhs));
1127     }
1128   }
1129 
1130   /// Destroys the stored value if there is one.
1131   ~optional() = default;
1132 
1133   /// Assignment to empty.
1134   ///
1135   /// Destroys the current value if there is one.
operator =(nullopt_t)1136   optional &operator=(nullopt_t) noexcept {
1137     if (has_value()) {
1138       this->m_value.~T();
1139       this->m_has_value = false;
1140     }
1141 
1142     return *this;
1143   }
1144 
1145   /// Copy assignment.
1146   ///
1147   /// Copies the value from `rhs` if there is one. Otherwise resets the stored
1148   /// value in `*this`.
1149   optional &operator=(const optional &rhs) = default;
1150 
1151   /// Move assignment.
1152   ///
1153   /// Moves the value from `rhs` if there is one. Otherwise resets the stored
1154   /// value in `*this`.
1155   optional &operator=(optional &&rhs) = default;
1156 
1157   /// Assigns the stored value from `u`, destroying the old value if there was
1158   /// one.
1159   template <class U = T, detail::enable_assign_forward<T, U> * = nullptr>
operator =(U && u)1160   optional &operator=(U &&u) {
1161     if (has_value()) {
1162       this->m_value = std::forward<U>(u);
1163     } else {
1164       this->construct(std::forward<U>(u));
1165     }
1166 
1167     return *this;
1168   }
1169 
1170   /// Converting copy assignment operator.
1171   ///
1172   /// Copies the value from `rhs` if there is one. Otherwise resets the stored
1173   /// value in `*this`.
1174   template <class U,
1175             detail::enable_assign_from_other<T, U, const U &> * = nullptr>
operator =(const optional<U> & rhs)1176   optional &operator=(const optional<U> &rhs) {
1177     if (has_value()) {
1178       if (rhs.has_value()) {
1179         this->m_value = *rhs;
1180       } else {
1181         this->hard_reset();
1182       }
1183     }
1184 
1185     if (rhs.has_value()) {
1186       this->construct(*rhs);
1187     }
1188 
1189     return *this;
1190   }
1191 
1192   // TODO check exception guarantee
1193   /// Converting move assignment operator.
1194   ///
1195   /// Moves the value from `rhs` if there is one. Otherwise resets the stored
1196   /// value in `*this`.
1197   template <class U, detail::enable_assign_from_other<T, U, U> * = nullptr>
operator =(optional<U> && rhs)1198   optional &operator=(optional<U> &&rhs) {
1199     if (has_value()) {
1200       if (rhs.has_value()) {
1201         this->m_value = std::move(*rhs);
1202       } else {
1203         this->hard_reset();
1204       }
1205     }
1206 
1207     if (rhs.has_value()) {
1208       this->construct(std::move(*rhs));
1209     }
1210 
1211     return *this;
1212   }
1213 
1214   /// Constructs the value in-place, destroying the current one if there is
1215   /// one.
emplace(Args &&...args)1216   template <class... Args> T &emplace(Args &&... args) {
1217     static_assert(std::is_constructible<T, Args &&...>::value,
1218                   "T must be constructible with Args");
1219 
1220     *this = nullopt;
1221     this->construct(std::forward<Args>(args)...);
1222     return value();
1223   }
1224 
1225   template <class U, class... Args>
1226   detail::enable_if_t<
1227       std::is_constructible<T, std::initializer_list<U> &, Args &&...>::value,
1228       T &>
emplace(std::initializer_list<U> il,Args &&...args)1229   emplace(std::initializer_list<U> il, Args &&... args) {
1230     *this = nullopt;
1231     this->construct(il, std::forward<Args>(args)...);
1232     return value();
1233   }
1234 
1235   /// Swaps this optional with the other.
1236   ///
1237   /// If neither optionals have a value, nothing happens.
1238   /// If both have a value, the values are swapped.
1239   /// If one has a value, it is moved to the other and the movee is left
1240   /// valueless.
1241   void
swap(optional & rhs)1242   swap(optional &rhs) noexcept(std::is_nothrow_move_constructible<T>::value
1243                                    &&detail::is_nothrow_swappable<T>::value) {
1244     using std::swap;
1245     if (has_value()) {
1246       if (rhs.has_value()) {
1247         swap(**this, *rhs);
1248       } else {
1249         new (std::addressof(rhs.m_value)) T(std::move(this->m_value));
1250         this->m_value.T::~T();
1251       }
1252     } else if (rhs.has_value()) {
1253       new (std::addressof(this->m_value)) T(std::move(rhs.m_value));
1254       rhs.m_value.T::~T();
1255     }
1256     swap(this->m_has_value, rhs.m_has_value);
1257   }
1258 
1259   /// Returns a pointer to the stored value
operator ->() const1260   constexpr const T *operator->() const {
1261     return std::addressof(this->m_value);
1262   }
1263 
operator ->()1264   TL_OPTIONAL_11_CONSTEXPR T *operator->() {
1265     return std::addressof(this->m_value);
1266   }
1267 
1268   /// Returns the stored value
operator *()1269   TL_OPTIONAL_11_CONSTEXPR T &operator*() & { return this->m_value; }
1270 
operator *() const1271   constexpr const T &operator*() const & { return this->m_value; }
1272 
operator *()1273   TL_OPTIONAL_11_CONSTEXPR T &&operator*() && {
1274     return std::move(this->m_value);
1275   }
1276 
1277 #ifndef TL_OPTIONAL_NO_CONSTRR
operator *() const1278   constexpr const T &&operator*() const && { return std::move(this->m_value); }
1279 #endif
1280 
1281   /// Returns whether or not the optional has a value
has_value() const1282   constexpr bool has_value() const noexcept { return this->m_has_value; }
1283 
operator bool() const1284   constexpr explicit operator bool() const noexcept {
1285     return this->m_has_value;
1286   }
1287 
1288   /// Returns the contained value if there is one, otherwise throws bad_optional_access
value()1289   TL_OPTIONAL_11_CONSTEXPR T &value() & {
1290     if (has_value())
1291       return this->m_value;
1292     throw bad_optional_access();
1293   }
value() const1294   TL_OPTIONAL_11_CONSTEXPR const T &value() const & {
1295     if (has_value())
1296       return this->m_value;
1297     throw bad_optional_access();
1298   }
value()1299   TL_OPTIONAL_11_CONSTEXPR T &&value() && {
1300     if (has_value())
1301       return std::move(this->m_value);
1302     throw bad_optional_access();
1303   }
1304 
1305 #ifndef TL_OPTIONAL_NO_CONSTRR
value() const1306   TL_OPTIONAL_11_CONSTEXPR const T &&value() const && {
1307     if (has_value())
1308       return std::move(this->m_value);
1309     throw bad_optional_access();
1310   }
1311 #endif
1312 
1313   /// Returns the stored value if there is one, otherwise returns `u`
value_or(U && u) const1314   template <class U> constexpr T value_or(U &&u) const & {
1315     static_assert(std::is_copy_constructible<T>::value &&
1316                       std::is_convertible<U &&, T>::value,
1317                   "T must be copy constructible and convertible from U");
1318     return has_value() ? **this : static_cast<T>(std::forward<U>(u));
1319   }
1320 
value_or(U && u)1321   template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && {
1322     static_assert(std::is_move_constructible<T>::value &&
1323                       std::is_convertible<U &&, T>::value,
1324                   "T must be move constructible and convertible from U");
1325     return has_value() ? **this : static_cast<T>(std::forward<U>(u));
1326   }
1327 
1328   /// Destroys the stored value if one exists, making the optional empty
reset()1329   void reset() noexcept {
1330     if (has_value()) {
1331       this->m_value.~T();
1332       this->m_has_value = false;
1333     }
1334   }
1335 }; // namespace tl
1336 
1337 /// Compares two optional objects
1338 template <class T, class U>
operator ==(const optional<T> & lhs,const optional<U> & rhs)1339 inline constexpr bool operator==(const optional<T> &lhs,
1340                                  const optional<U> &rhs) {
1341   return lhs.has_value() == rhs.has_value() &&
1342          (!lhs.has_value() || *lhs == *rhs);
1343 }
1344 template <class T, class U>
operator !=(const optional<T> & lhs,const optional<U> & rhs)1345 inline constexpr bool operator!=(const optional<T> &lhs,
1346                                  const optional<U> &rhs) {
1347   return lhs.has_value() != rhs.has_value() ||
1348          (lhs.has_value() && *lhs != *rhs);
1349 }
1350 template <class T, class U>
operator <(const optional<T> & lhs,const optional<U> & rhs)1351 inline constexpr bool operator<(const optional<T> &lhs,
1352                                 const optional<U> &rhs) {
1353   return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs);
1354 }
1355 template <class T, class U>
operator >(const optional<T> & lhs,const optional<U> & rhs)1356 inline constexpr bool operator>(const optional<T> &lhs,
1357                                 const optional<U> &rhs) {
1358   return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs);
1359 }
1360 template <class T, class U>
operator <=(const optional<T> & lhs,const optional<U> & rhs)1361 inline constexpr bool operator<=(const optional<T> &lhs,
1362                                  const optional<U> &rhs) {
1363   return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs);
1364 }
1365 template <class T, class U>
operator >=(const optional<T> & lhs,const optional<U> & rhs)1366 inline constexpr bool operator>=(const optional<T> &lhs,
1367                                  const optional<U> &rhs) {
1368   return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs);
1369 }
1370 
1371 /// Compares an optional to a `nullopt`
1372 template <class T>
operator ==(const optional<T> & lhs,nullopt_t)1373 inline constexpr bool operator==(const optional<T> &lhs, nullopt_t) noexcept {
1374   return !lhs.has_value();
1375 }
1376 template <class T>
operator ==(nullopt_t,const optional<T> & rhs)1377 inline constexpr bool operator==(nullopt_t, const optional<T> &rhs) noexcept {
1378   return !rhs.has_value();
1379 }
1380 template <class T>
operator !=(const optional<T> & lhs,nullopt_t)1381 inline constexpr bool operator!=(const optional<T> &lhs, nullopt_t) noexcept {
1382   return lhs.has_value();
1383 }
1384 template <class T>
operator !=(nullopt_t,const optional<T> & rhs)1385 inline constexpr bool operator!=(nullopt_t, const optional<T> &rhs) noexcept {
1386   return rhs.has_value();
1387 }
1388 template <class T>
operator <(const optional<T> &,nullopt_t)1389 inline constexpr bool operator<(const optional<T> &, nullopt_t) noexcept {
1390   return false;
1391 }
1392 template <class T>
operator <(nullopt_t,const optional<T> & rhs)1393 inline constexpr bool operator<(nullopt_t, const optional<T> &rhs) noexcept {
1394   return rhs.has_value();
1395 }
1396 template <class T>
operator <=(const optional<T> & lhs,nullopt_t)1397 inline constexpr bool operator<=(const optional<T> &lhs, nullopt_t) noexcept {
1398   return !lhs.has_value();
1399 }
1400 template <class T>
operator <=(nullopt_t,const optional<T> &)1401 inline constexpr bool operator<=(nullopt_t, const optional<T> &) noexcept {
1402   return true;
1403 }
1404 template <class T>
operator >(const optional<T> & lhs,nullopt_t)1405 inline constexpr bool operator>(const optional<T> &lhs, nullopt_t) noexcept {
1406   return lhs.has_value();
1407 }
1408 template <class T>
operator >(nullopt_t,const optional<T> &)1409 inline constexpr bool operator>(nullopt_t, const optional<T> &) noexcept {
1410   return false;
1411 }
1412 template <class T>
operator >=(const optional<T> &,nullopt_t)1413 inline constexpr bool operator>=(const optional<T> &, nullopt_t) noexcept {
1414   return true;
1415 }
1416 template <class T>
operator >=(nullopt_t,const optional<T> & rhs)1417 inline constexpr bool operator>=(nullopt_t, const optional<T> &rhs) noexcept {
1418   return !rhs.has_value();
1419 }
1420 
1421 /// Compares the optional with a value.
1422 template <class T, class U>
operator ==(const optional<T> & lhs,const U & rhs)1423 inline constexpr bool operator==(const optional<T> &lhs, const U &rhs) {
1424   return lhs.has_value() ? *lhs == rhs : false;
1425 }
1426 template <class T, class U>
operator ==(const U & lhs,const optional<T> & rhs)1427 inline constexpr bool operator==(const U &lhs, const optional<T> &rhs) {
1428   return rhs.has_value() ? lhs == *rhs : false;
1429 }
1430 template <class T, class U>
operator !=(const optional<T> & lhs,const U & rhs)1431 inline constexpr bool operator!=(const optional<T> &lhs, const U &rhs) {
1432   return lhs.has_value() ? *lhs != rhs : true;
1433 }
1434 template <class T, class U>
operator !=(const U & lhs,const optional<T> & rhs)1435 inline constexpr bool operator!=(const U &lhs, const optional<T> &rhs) {
1436   return rhs.has_value() ? lhs != *rhs : true;
1437 }
1438 template <class T, class U>
operator <(const optional<T> & lhs,const U & rhs)1439 inline constexpr bool operator<(const optional<T> &lhs, const U &rhs) {
1440   return lhs.has_value() ? *lhs < rhs : true;
1441 }
1442 template <class T, class U>
operator <(const U & lhs,const optional<T> & rhs)1443 inline constexpr bool operator<(const U &lhs, const optional<T> &rhs) {
1444   return rhs.has_value() ? lhs < *rhs : false;
1445 }
1446 template <class T, class U>
operator <=(const optional<T> & lhs,const U & rhs)1447 inline constexpr bool operator<=(const optional<T> &lhs, const U &rhs) {
1448   return lhs.has_value() ? *lhs <= rhs : true;
1449 }
1450 template <class T, class U>
operator <=(const U & lhs,const optional<T> & rhs)1451 inline constexpr bool operator<=(const U &lhs, const optional<T> &rhs) {
1452   return rhs.has_value() ? lhs <= *rhs : false;
1453 }
1454 template <class T, class U>
operator >(const optional<T> & lhs,const U & rhs)1455 inline constexpr bool operator>(const optional<T> &lhs, const U &rhs) {
1456   return lhs.has_value() ? *lhs > rhs : false;
1457 }
1458 template <class T, class U>
operator >(const U & lhs,const optional<T> & rhs)1459 inline constexpr bool operator>(const U &lhs, const optional<T> &rhs) {
1460   return rhs.has_value() ? lhs > *rhs : true;
1461 }
1462 template <class T, class U>
operator >=(const optional<T> & lhs,const U & rhs)1463 inline constexpr bool operator>=(const optional<T> &lhs, const U &rhs) {
1464   return lhs.has_value() ? *lhs >= rhs : false;
1465 }
1466 template <class T, class U>
operator >=(const U & lhs,const optional<T> & rhs)1467 inline constexpr bool operator>=(const U &lhs, const optional<T> &rhs) {
1468   return rhs.has_value() ? lhs >= *rhs : true;
1469 }
1470 
1471 template <class T,
1472           detail::enable_if_t<std::is_move_constructible<T>::value> * = nullptr,
1473           detail::enable_if_t<detail::is_swappable<T>::value> * = nullptr>
swap(optional<T> & lhs,optional<T> & rhs)1474 void swap(optional<T> &lhs,
1475           optional<T> &rhs) noexcept(noexcept(lhs.swap(rhs))) {
1476   return lhs.swap(rhs);
1477 }
1478 
1479 namespace detail {
1480 struct i_am_secret {};
1481 } // namespace detail
1482 
1483 template <class T = detail::i_am_secret, class U,
1484           class Ret =
1485               detail::conditional_t<std::is_same<T, detail::i_am_secret>::value,
1486                                     detail::decay_t<U>, T>>
make_optional(U && v)1487 inline constexpr optional<Ret> make_optional(U &&v) {
1488   return optional<Ret>(std::forward<U>(v));
1489 }
1490 
1491 template <class T, class... Args>
make_optional(Args &&...args)1492 inline constexpr optional<T> make_optional(Args &&... args) {
1493   return optional<T>(in_place, std::forward<Args>(args)...);
1494 }
1495 template <class T, class U, class... Args>
make_optional(std::initializer_list<U> il,Args &&...args)1496 inline constexpr optional<T> make_optional(std::initializer_list<U> il,
1497                                            Args &&... args) {
1498   return optional<T>(in_place, il, std::forward<Args>(args)...);
1499 }
1500 
1501 #if __cplusplus >= 201703L
1502 template <class T> optional(T)->optional<T>;
1503 #endif
1504 
1505 /// \exclude
1506 namespace detail {
1507 #ifdef TL_OPTIONAL_CXX14
1508 template <class Opt, class F,
1509           class Ret = decltype(detail::invoke(std::declval<F>(),
1510                                               *std::declval<Opt>())),
1511           detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
optional_map_impl(Opt && opt,F && f)1512 constexpr auto optional_map_impl(Opt &&opt, F &&f) {
1513   return opt.has_value()
1514              ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))
1515              : optional<Ret>(nullopt);
1516 }
1517 
1518 template <class Opt, class F,
1519           class Ret = decltype(detail::invoke(std::declval<F>(),
1520                                               *std::declval<Opt>())),
1521           detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
optional_map_impl(Opt && opt,F && f)1522 auto optional_map_impl(Opt &&opt, F &&f) {
1523   if (opt.has_value()) {
1524     detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
1525     return make_optional(monostate{});
1526   }
1527 
1528   return optional<monostate>(nullopt);
1529 }
1530 #else
1531 template <class Opt, class F,
1532           class Ret = decltype(detail::invoke(std::declval<F>(),
1533                                               *std::declval<Opt>())),
1534           detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
1535 
1536 constexpr auto optional_map_impl(Opt &&opt, F &&f) -> optional<Ret> {
1537   return opt.has_value()
1538              ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))
1539              : optional<Ret>(nullopt);
1540 }
1541 
1542 template <class Opt, class F,
1543           class Ret = decltype(detail::invoke(std::declval<F>(),
1544                                               *std::declval<Opt>())),
1545           detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
1546 
1547 auto optional_map_impl(Opt &&opt, F &&f) -> optional<monostate> {
1548   if (opt.has_value()) {
1549     detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
1550     return monostate{};
1551   }
1552 
1553   return nullopt;
1554 }
1555 #endif
1556 } // namespace detail
1557 
1558 /// Specialization for when `T` is a reference. `optional<T&>` acts similarly
1559 /// to a `T*`, but provides more operations and shows intent more clearly.
1560 template <class T> class optional<T &> {
1561 public:
1562 // The different versions for C++14 and 11 are needed because deduced return
1563 // types are not SFINAE-safe. This provides better support for things like
1564 // generic lambdas. C.f.
1565 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html
1566 #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \
1567     !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
1568 
1569   /// Carries out some operation which returns an optional on the stored
1570   /// object if there is one.
and_then(F && f)1571   template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) & {
1572     using result = detail::invoke_result_t<F, T &>;
1573     static_assert(detail::is_optional<result>::value,
1574                   "F must return an optional");
1575 
1576     return has_value() ? detail::invoke(std::forward<F>(f), **this)
1577                        : result(nullopt);
1578   }
1579 
and_then(F && f)1580   template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) && {
1581     using result = detail::invoke_result_t<F, T &>;
1582     static_assert(detail::is_optional<result>::value,
1583                   "F must return an optional");
1584 
1585     return has_value() ? detail::invoke(std::forward<F>(f), **this)
1586                        : result(nullopt);
1587   }
1588 
and_then(F && f) const1589   template <class F> constexpr auto and_then(F &&f) const & {
1590     using result = detail::invoke_result_t<F, const T &>;
1591     static_assert(detail::is_optional<result>::value,
1592                   "F must return an optional");
1593 
1594     return has_value() ? detail::invoke(std::forward<F>(f), **this)
1595                        : result(nullopt);
1596   }
1597 
1598 #ifndef TL_OPTIONAL_NO_CONSTRR
and_then(F && f) const1599   template <class F> constexpr auto and_then(F &&f) const && {
1600     using result = detail::invoke_result_t<F, const T &>;
1601     static_assert(detail::is_optional<result>::value,
1602                   "F must return an optional");
1603 
1604     return has_value() ? detail::invoke(std::forward<F>(f), **this)
1605                        : result(nullopt);
1606   }
1607 #endif
1608 #else
1609   /// Carries out some operation which returns an optional on the stored
1610   /// object if there is one.
1611   template <class F>
1612   TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) & {
1613     using result = detail::invoke_result_t<F, T &>;
1614     static_assert(detail::is_optional<result>::value,
1615                   "F must return an optional");
1616 
1617     return has_value() ? detail::invoke(std::forward<F>(f), **this)
1618                        : result(nullopt);
1619   }
1620 
1621   template <class F>
1622   TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) && {
1623     using result = detail::invoke_result_t<F, T &>;
1624     static_assert(detail::is_optional<result>::value,
1625                   "F must return an optional");
1626 
1627     return has_value() ? detail::invoke(std::forward<F>(f), **this)
1628                        : result(nullopt);
1629   }
1630 
1631   template <class F>
1632   constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const & {
1633     using result = detail::invoke_result_t<F, const T &>;
1634     static_assert(detail::is_optional<result>::value,
1635                   "F must return an optional");
1636 
1637     return has_value() ? detail::invoke(std::forward<F>(f), **this)
1638                        : result(nullopt);
1639   }
1640 
1641 #ifndef TL_OPTIONAL_NO_CONSTRR
1642   template <class F>
1643   constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const && {
1644     using result = detail::invoke_result_t<F, const T &>;
1645     static_assert(detail::is_optional<result>::value,
1646                   "F must return an optional");
1647 
1648     return has_value() ? detail::invoke(std::forward<F>(f), **this)
1649                        : result(nullopt);
1650   }
1651 #endif
1652 #endif
1653 
1654 #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \
1655     !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
1656   /// Carries out some operation on the stored object if there is one.
map(F && f)1657   template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) & {
1658     return detail::optional_map_impl(*this, std::forward<F>(f));
1659   }
1660 
map(F && f)1661   template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) && {
1662     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1663   }
1664 
map(F && f) const1665   template <class F> constexpr auto map(F &&f) const & {
1666     return detail::optional_map_impl(*this, std::forward<F>(f));
1667   }
1668 
map(F && f) const1669   template <class F> constexpr auto map(F &&f) const && {
1670     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1671   }
1672 #else
1673   /// Carries out some operation on the stored object if there is one.
1674   template <class F>
optional_map_impl(std::declval<optional &> (),std::declval<F &&> ())1675   TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional &>(),
1676                                                      std::declval<F &&>()))
1677   map(F &&f) & {
1678     return detail::optional_map_impl(*this, std::forward<F>(f));
1679   }
1680 
1681   template <class F>
optional_map_impl(std::declval<optional &&> (),std::declval<F &&> ())1682   TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional &&>(),
1683                                                      std::declval<F &&>()))
1684   map(F &&f) && {
1685     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1686   }
1687 
1688   template <class F>
optional_map_impl(std::declval<const optional &> (),std::declval<F &&> ())1689   constexpr decltype(detail::optional_map_impl(std::declval<const optional &>(),
1690                                       std::declval<F &&>()))
1691   map(F &&f) const & {
1692     return detail::optional_map_impl(*this, std::forward<F>(f));
1693   }
1694 
1695 #ifndef TL_OPTIONAL_NO_CONSTRR
1696   template <class F>
optional_map_impl(std::declval<const optional &&> (),std::declval<F &&> ())1697   constexpr decltype(detail::optional_map_impl(std::declval<const optional &&>(),
1698                                       std::declval<F &&>()))
1699   map(F &&f) const && {
1700     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1701   }
1702 #endif
1703 #endif
1704 
1705 #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) &&               \
1706     !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
1707   /// Carries out some operation on the stored object if there is one.
transform(F && f)1708   template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) & {
1709     return detail::optional_map_impl(*this, std::forward<F>(f));
1710   }
1711 
transform(F && f)1712   template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) && {
1713     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1714   }
1715 
transform(F && f) const1716   template <class F> constexpr auto transform(F&& f) const & {
1717     return detail::optional_map_impl(*this, std::forward<F>(f));
1718   }
1719 
transform(F && f) const1720   template <class F> constexpr auto transform(F&& f) const && {
1721     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1722   }
1723 #else
1724   /// Carries out some operation on the stored object if there is one.
1725   template <class F>
optional_map_impl(std::declval<optional &> (),std::declval<F &&> ())1726   TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&>(),
1727     std::declval<F&&>()))
1728     transform(F&& f) & {
1729     return detail::optional_map_impl(*this, std::forward<F>(f));
1730   }
1731 
1732   /// \group map
1733   /// \synopsis template <class F> auto transform(F &&f) &&;
1734   template <class F>
optional_map_impl(std::declval<optional &&> (),std::declval<F &&> ())1735   TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&&>(),
1736     std::declval<F&&>()))
1737     transform(F&& f) && {
1738     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1739   }
1740 
1741   template <class F>
optional_map_impl(std::declval<const optional &> (),std::declval<F &&> ())1742   constexpr decltype(detail::optional_map_impl(std::declval<const optional&>(),
1743     std::declval<F&&>()))
1744     transform(F&& f) const & {
1745     return detail::optional_map_impl(*this, std::forward<F>(f));
1746   }
1747 
1748 #ifndef TL_OPTIONAL_NO_CONSTRR
1749   template <class F>
optional_map_impl(std::declval<const optional &&> (),std::declval<F &&> ())1750   constexpr decltype(detail::optional_map_impl(std::declval<const optional&&>(),
1751     std::declval<F&&>()))
1752     transform(F&& f) const && {
1753     return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1754   }
1755 #endif
1756 #endif
1757 
1758   /// Calls `f` if the optional is empty
1759   template <class F, detail::enable_if_ret_void<F> * = nullptr>
or_else(F && f)1760   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {
1761     if (has_value())
1762       return *this;
1763 
1764     std::forward<F>(f)();
1765     return nullopt;
1766   }
1767 
1768   template <class F, detail::disable_if_ret_void<F> * = nullptr>
or_else(F && f)1769   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {
1770     return has_value() ? *this : std::forward<F>(f)();
1771   }
1772 
1773   template <class F, detail::enable_if_ret_void<F> * = nullptr>
or_else(F && f)1774   optional<T> or_else(F &&f) && {
1775     if (has_value())
1776       return std::move(*this);
1777 
1778     std::forward<F>(f)();
1779     return nullopt;
1780   }
1781 
1782   template <class F, detail::disable_if_ret_void<F> * = nullptr>
or_else(F && f)1783   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) && {
1784     return has_value() ? std::move(*this) : std::forward<F>(f)();
1785   }
1786 
1787   template <class F, detail::enable_if_ret_void<F> * = nullptr>
or_else(F && f) const1788   optional<T> or_else(F &&f) const & {
1789     if (has_value())
1790       return *this;
1791 
1792     std::forward<F>(f)();
1793     return nullopt;
1794   }
1795 
1796   template <class F, detail::disable_if_ret_void<F> * = nullptr>
or_else(F && f) const1797   optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) const & {
1798     return has_value() ? *this : std::forward<F>(f)();
1799   }
1800 
1801 #ifndef TL_OPTIONAL_NO_CONSTRR
1802   template <class F, detail::enable_if_ret_void<F> * = nullptr>
or_else(F && f) const1803   optional<T> or_else(F &&f) const && {
1804     if (has_value())
1805       return std::move(*this);
1806 
1807     std::forward<F>(f)();
1808     return nullopt;
1809   }
1810 
1811   template <class F, detail::disable_if_ret_void<F> * = nullptr>
or_else(F && f) const1812   optional<T> or_else(F &&f) const && {
1813     return has_value() ? std::move(*this) : std::forward<F>(f)();
1814   }
1815 #endif
1816 
1817   /// Maps the stored value with `f` if there is one, otherwise returns `u`
map_or(F && f,U && u)1818   template <class F, class U> U map_or(F &&f, U &&u) & {
1819     return has_value() ? detail::invoke(std::forward<F>(f), **this)
1820                        : std::forward<U>(u);
1821   }
1822 
map_or(F && f,U && u)1823   template <class F, class U> U map_or(F &&f, U &&u) && {
1824     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
1825                        : std::forward<U>(u);
1826   }
1827 
map_or(F && f,U && u) const1828   template <class F, class U> U map_or(F &&f, U &&u) const & {
1829     return has_value() ? detail::invoke(std::forward<F>(f), **this)
1830                        : std::forward<U>(u);
1831   }
1832 
1833 #ifndef TL_OPTIONAL_NO_CONSTRR
map_or(F && f,U && u) const1834   template <class F, class U> U map_or(F &&f, U &&u) const && {
1835     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
1836                        : std::forward<U>(u);
1837   }
1838 #endif
1839 
1840   /// Maps the stored value with `f` if there is one, otherwise calls
1841   /// `u` and returns the result.
1842   template <class F, class U>
map_or_else(F && f,U && u)1843   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) & {
1844     return has_value() ? detail::invoke(std::forward<F>(f), **this)
1845                        : std::forward<U>(u)();
1846   }
1847 
1848   template <class F, class U>
map_or_else(F && f,U && u)1849   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) && {
1850     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
1851                        : std::forward<U>(u)();
1852   }
1853 
1854   template <class F, class U>
map_or_else(F && f,U && u) const1855   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const & {
1856     return has_value() ? detail::invoke(std::forward<F>(f), **this)
1857                        : std::forward<U>(u)();
1858   }
1859 
1860 #ifndef TL_OPTIONAL_NO_CONSTRR
1861   template <class F, class U>
map_or_else(F && f,U && u) const1862   detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const && {
1863     return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
1864                        : std::forward<U>(u)();
1865   }
1866 #endif
1867 
1868   /// Returns `u` if `*this` has a value, otherwise an empty optional.
1869   template <class U>
conjunction(U && u) const1870   constexpr optional<typename std::decay<U>::type> conjunction(U &&u) const {
1871     using result = optional<detail::decay_t<U>>;
1872     return has_value() ? result{u} : result{nullopt};
1873   }
1874 
1875   /// Returns `rhs` if `*this` is empty, otherwise the current value.
disjunction(const optional & rhs)1876   TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) & {
1877     return has_value() ? *this : rhs;
1878   }
1879 
disjunction(const optional & rhs) const1880   constexpr optional disjunction(const optional &rhs) const & {
1881     return has_value() ? *this : rhs;
1882   }
1883 
disjunction(const optional & rhs)1884   TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) && {
1885     return has_value() ? std::move(*this) : rhs;
1886   }
1887 
1888 #ifndef TL_OPTIONAL_NO_CONSTRR
disjunction(const optional & rhs) const1889   constexpr optional disjunction(const optional &rhs) const && {
1890     return has_value() ? std::move(*this) : rhs;
1891   }
1892 #endif
1893 
disjunction(optional && rhs)1894   TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) & {
1895     return has_value() ? *this : std::move(rhs);
1896   }
1897 
disjunction(optional && rhs) const1898   constexpr optional disjunction(optional &&rhs) const & {
1899     return has_value() ? *this : std::move(rhs);
1900   }
1901 
disjunction(optional && rhs)1902   TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) && {
1903     return has_value() ? std::move(*this) : std::move(rhs);
1904   }
1905 
1906 #ifndef TL_OPTIONAL_NO_CONSTRR
disjunction(optional && rhs) const1907   constexpr optional disjunction(optional &&rhs) const && {
1908     return has_value() ? std::move(*this) : std::move(rhs);
1909   }
1910 #endif
1911 
1912   /// Takes the value out of the optional, leaving it empty
take()1913   optional take() {
1914     optional ret = std::move(*this);
1915     reset();
1916     return ret;
1917   }
1918 
1919   using value_type = T &;
1920 
1921   /// Constructs an optional that does not contain a value.
optional()1922   constexpr optional() noexcept : m_value(nullptr) {}
1923 
optional(nullopt_t)1924   constexpr optional(nullopt_t) noexcept : m_value(nullptr) {}
1925 
1926   /// Copy constructor
1927   ///
1928   /// If `rhs` contains a value, the stored value is direct-initialized with
1929   /// it. Otherwise, the constructed optional is empty.
1930   TL_OPTIONAL_11_CONSTEXPR optional(const optional &rhs) noexcept = default;
1931 
1932   /// Move constructor
1933   ///
1934   /// If `rhs` contains a value, the stored value is direct-initialized with
1935   /// it. Otherwise, the constructed optional is empty.
1936   TL_OPTIONAL_11_CONSTEXPR optional(optional &&rhs) = default;
1937 
1938   /// Constructs the stored value with `u`.
1939   template <class U = T,
1940             detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>
1941                 * = nullptr>
optional(U && u)1942   constexpr optional(U &&u)  noexcept : m_value(std::addressof(u)) {
1943     static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue");
1944   }
1945 
1946   template <class U>
optional(const optional<U> & rhs)1947   constexpr explicit optional(const optional<U> &rhs) noexcept : optional(*rhs) {}
1948 
1949   /// No-op
1950   ~optional() = default;
1951 
1952   /// Assignment to empty.
1953   ///
1954   /// Destroys the current value if there is one.
operator =(nullopt_t)1955   optional &operator=(nullopt_t) noexcept {
1956     m_value = nullptr;
1957     return *this;
1958   }
1959 
1960   /// Copy assignment.
1961   ///
1962   /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
1963   /// resets the stored value in `*this`.
1964   optional &operator=(const optional &rhs) = default;
1965 
1966   /// Rebinds this optional to `u`.
1967   template <class U = T,
1968             detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>
1969                 * = nullptr>
operator =(U && u)1970   optional &operator=(U &&u) {
1971     static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue");
1972     m_value = std::addressof(u);
1973     return *this;
1974   }
1975 
1976   /// Converting copy assignment operator.
1977   ///
1978   /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
1979   /// resets the stored value in `*this`.
operator =(const optional<U> & rhs)1980   template <class U> optional &operator=(const optional<U> &rhs) noexcept {
1981     m_value = std::addressof(rhs.value());
1982     return *this;
1983   }
1984 
1985   /// Rebinds this optional to `u`.
1986   template <class U = T,
1987             detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>
1988                 * = nullptr>
emplace(U && u)1989   optional &emplace(U &&u) noexcept {
1990     return *this = std::forward<U>(u);
1991   }
1992 
swap(optional & rhs)1993   void swap(optional &rhs) noexcept { std::swap(m_value, rhs.m_value); }
1994 
1995   /// Returns a pointer to the stored value
operator ->() const1996   constexpr const T *operator->() const noexcept { return m_value; }
1997 
operator ->()1998   TL_OPTIONAL_11_CONSTEXPR T *operator->() noexcept { return m_value; }
1999 
2000   /// Returns the stored value
operator *()2001   TL_OPTIONAL_11_CONSTEXPR T &operator*() noexcept { return *m_value; }
2002 
operator *() const2003   constexpr const T &operator*() const noexcept { return *m_value; }
2004 
has_value() const2005   constexpr bool has_value() const noexcept { return m_value != nullptr; }
2006 
operator bool() const2007   constexpr explicit operator bool() const noexcept {
2008     return m_value != nullptr;
2009   }
2010 
2011   /// Returns the contained value if there is one, otherwise throws bad_optional_access
value()2012   TL_OPTIONAL_11_CONSTEXPR T &value() {
2013     if (has_value())
2014       return *m_value;
2015     throw bad_optional_access();
2016   }
value() const2017   TL_OPTIONAL_11_CONSTEXPR const T &value() const {
2018     if (has_value())
2019       return *m_value;
2020     throw bad_optional_access();
2021   }
2022 
2023   /// Returns the stored value if there is one, otherwise returns `u`
value_or(U && u) const2024   template <class U> constexpr T value_or(U &&u) const & noexcept {
2025     static_assert(std::is_copy_constructible<T>::value &&
2026                       std::is_convertible<U &&, T>::value,
2027                   "T must be copy constructible and convertible from U");
2028     return has_value() ? **this : static_cast<T>(std::forward<U>(u));
2029   }
2030 
2031   /// \group value_or
value_or(U && u)2032   template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && noexcept {
2033     static_assert(std::is_move_constructible<T>::value &&
2034                       std::is_convertible<U &&, T>::value,
2035                   "T must be move constructible and convertible from U");
2036     return has_value() ? **this : static_cast<T>(std::forward<U>(u));
2037   }
2038 
2039   /// Destroys the stored value if one exists, making the optional empty
reset()2040   void reset() noexcept { m_value = nullptr; }
2041 
2042 private:
2043   T *m_value;
2044 }; // namespace tl
2045 
2046 
2047 
2048 } // namespace tl
2049 
2050 namespace std {
2051 // TODO SFINAE
2052 template <class T> struct hash<tl::optional<T>> {
operator ()std::hash2053   ::std::size_t operator()(const tl::optional<T> &o) const {
2054     if (!o.has_value())
2055       return 0;
2056 
2057     return std::hash<tl::detail::remove_const_t<T>>()(*o);
2058   }
2059 };
2060 } // namespace std
2061 
2062 #endif
2063