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