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