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