Line data Source code
1 : // clang-format off
2 :
3 : ///
4 : // optional - An implementation of std::optional with extensions
5 : // Written in 2017 by Sy Brand (tartanllama@gmail.com, @TartanLlama)
6 : //
7 : // Documentation available at https://tl.tartanllama.xyz/
8 : //
9 : // To the extent possible under law, the author(s) have dedicated all
10 : // copyright and related and neighboring rights to this software to the
11 : // public domain worldwide. This software is distributed without any warranty.
12 : //
13 : // You should have received a copy of the CC0 Public Domain Dedication
14 : // along with this software. If not, see
15 : // <http://creativecommons.org/publicdomain/zero/1.0/>.
16 : ///
17 :
18 : #ifndef TL_OPTIONAL_HPP
19 : #define TL_OPTIONAL_HPP
20 :
21 : #define TL_OPTIONAL_VERSION_MAJOR 1
22 : #define TL_OPTIONAL_VERSION_MINOR 1
23 : #define TL_OPTIONAL_VERSION_PATCH 0
24 :
25 : #include "rust-system.h"
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_TRAITS_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_TRAITS_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_TRAITS_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>
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>>
183 265418 : 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 291906 : 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 {
356 8625065 : TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
357 8546155 : : m_dummy(), m_has_value(false) {}
358 :
359 : template <class... U>
360 1251983 : TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u)
361 1708097 : : m_value(std::forward<U>(u)...), m_has_value(true) {}
362 :
363 7279290 : ~optional_storage_base() {
364 2987265 : if (m_has_value) {
365 3393839 : m_value.~T();
366 : m_has_value = false;
367 : }
368 444 : }
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> {
381 264792 : TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
382 264792 : : m_dummy(), m_has_value(false) {}
383 :
384 : template <class... U>
385 7753545 : TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u)
386 7707273 : : 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 21856467 : template <class T> struct optional_operations_base : optional_storage_base<T> {
402 9850765 : using optional_storage_base<T>::optional_storage_base;
403 :
404 : void hard_reset() noexcept {
405 : get().~T();
406 : this->m_has_value = false;
407 : }
408 :
409 3762149 : template <class... Args> void construct(Args &&... args) {
410 4286657 : new (std::addressof(this->m_value)) T(std::forward<Args>(args)...);
411 3759202 : this->m_has_value = true;
412 3141872 : }
413 :
414 163191 : template <class Opt> void assign(Opt &&rhs) {
415 163191 : if (this->has_value()) {
416 667 : if (rhs.has_value()) {
417 3583 : this->m_value = std::forward<Opt>(rhs).get();
418 : } else {
419 33 : this->m_value.~T();
420 33 : this->m_has_value = false;
421 : }
422 : }
423 :
424 162524 : else if (rhs.has_value()) {
425 136567 : construct(std::forward<Opt>(rhs).get());
426 : }
427 163191 : }
428 :
429 8124223 : bool has_value() const { return this->m_has_value; }
430 :
431 998655 : TL_OPTIONAL_11_CONSTEXPR T &get() & { return this->m_value; }
432 2344355 : TL_OPTIONAL_11_CONSTEXPR const T &get() const & { return this->m_value; }
433 111820 : TL_OPTIONAL_11_CONSTEXPR T &&get() && { return std::move(this->m_value); }
434 : #ifndef TL_OPTIONAL_NO_CONSTRR
435 : 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 264792 : struct optional_copy_base : optional_operations_base<T> {
443 7726251 : 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 12966987 : struct optional_copy_base<T, false> : optional_operations_base<T> {
449 2124658 : using optional_operations_base<T>::optional_operations_base;
450 :
451 2328634 : optional_copy_base() = default;
452 6296431 : optional_copy_base(const optional_copy_base &rhs)
453 6296431 : : optional_operations_base<T>() {
454 6296431 : if (rhs.has_value()) {
455 2473665 : this->construct(rhs.get());
456 : } else {
457 134 : this->m_has_value = false;
458 : }
459 6296431 : }
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 264792 : struct optional_move_base : optional_copy_base<T> {
474 7726251 : using optional_copy_base<T>::optional_copy_base;
475 : };
476 : #else
477 : template <class T, bool = false> struct optional_move_base;
478 : #endif
479 12966987 : template <class T> struct optional_move_base<T, false> : optional_copy_base<T> {
480 2124658 : using optional_copy_base<T>::optional_copy_base;
481 :
482 54907 : optional_move_base() = default;
483 1763600 : optional_move_base(const optional_move_base &rhs) = default;
484 :
485 2273727 : optional_move_base(optional_move_base &&rhs) noexcept(
486 2273727 : std::is_nothrow_move_constructible<T>::value) {
487 2247084 : if (rhs.has_value()) {
488 998655 : this->construct(std::move(rhs.get()));
489 : } else {
490 253618 : this->m_has_value = false;
491 : }
492 1896057 : }
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 264792 : struct optional_copy_assign_base : optional_move_base<T> {
502 7705200 : using optional_move_base<T>::optional_move_base;
503 : };
504 :
505 : template <class T>
506 12966987 : struct optional_copy_assign_base<T, false> : optional_move_base<T> {
507 2145709 : using optional_move_base<T>::optional_move_base;
508 :
509 54907 : optional_copy_assign_base() = default;
510 11044120 : optional_copy_assign_base(const optional_copy_assign_base &rhs) = default;
511 :
512 2407318 : optional_copy_assign_base(optional_copy_assign_base &&rhs) = default;
513 25394 : optional_copy_assign_base &operator=(const optional_copy_assign_base &rhs) {
514 25394 : 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 264792 : struct optional_move_assign_base : optional_copy_assign_base<T> {
531 7703635 : 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 12966987 : struct optional_move_assign_base<T, false> : optional_copy_assign_base<T> {
539 2145709 : using optional_copy_assign_base<T>::optional_copy_assign_base;
540 :
541 54907 : optional_move_assign_base() = default;
542 11044120 : optional_move_assign_base(const optional_move_assign_base &rhs) = default;
543 :
544 4314553 : optional_move_assign_base(optional_move_assign_base &&rhs) = default;
545 :
546 : optional_move_assign_base &
547 26450 : operator=(const optional_move_assign_base &rhs) = default;
548 :
549 : optional_move_assign_base &
550 135986 : operator=(optional_move_assign_base &&rhs) noexcept(
551 : std::is_nothrow_move_constructible<T>::value
552 : &&std::is_nothrow_move_assignable<T>::value) {
553 135986 : 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 {};
658 : 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 : /// An optional object is an object that contains the storage for another
665 : /// object and manages the lifetime of this contained object, if any. The
666 : /// contained object may be initialized after the optional object has been
667 : /// initialized, and may be destroyed before the optional object has been
668 : /// destroyed. The initialization state of the contained object is tracked by
669 : /// the optional object.
670 : template <class T>
671 : class optional : private detail::optional_move_assign_base<T>,
672 : private detail::optional_delete_ctor_base<T>,
673 : private detail::optional_delete_assign_base<T> {
674 : using base = detail::optional_move_assign_base<T>;
675 :
676 : static_assert(!std::is_same<T, in_place_t>::value,
677 : "instantiation of optional with in_place_t is ill-formed");
678 : static_assert(!std::is_same<detail::decay_t<T>, nullopt_t>::value,
679 : "instantiation of optional with nullopt_t is ill-formed");
680 :
681 : public:
682 : // The different versions for C++14 and 11 are needed because deduced return
683 : // types are not SFINAE-safe. This provides better support for things like
684 : // generic lambdas. C.f.
685 : // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html
686 : #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
687 : !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
688 : /// Carries out some operation which returns an optional on the stored
689 : /// object if there is one.
690 : template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) & {
691 : using result = detail::invoke_result_t<F, T &>;
692 : static_assert(detail::is_optional<result>::value,
693 : "F must return an optional");
694 :
695 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
696 : : result(nullopt);
697 : }
698 :
699 40870 : template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) && {
700 : using result = detail::invoke_result_t<F, T &&>;
701 : static_assert(detail::is_optional<result>::value,
702 : "F must return an optional");
703 :
704 39764 : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
705 1106 : : result(nullopt);
706 : }
707 :
708 : template <class F> constexpr auto and_then(F &&f) const & {
709 : using result = detail::invoke_result_t<F, const T &>;
710 : static_assert(detail::is_optional<result>::value,
711 : "F must return an optional");
712 :
713 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
714 : : result(nullopt);
715 : }
716 :
717 : #ifndef TL_OPTIONAL_NO_CONSTRR
718 : template <class F> constexpr auto and_then(F &&f) const && {
719 : using result = detail::invoke_result_t<F, const T &&>;
720 : static_assert(detail::is_optional<result>::value,
721 : "F must return an optional");
722 :
723 : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
724 : : result(nullopt);
725 : }
726 : #endif
727 : #else
728 : /// Carries out some operation which returns an optional on the stored
729 : /// object if there is one.
730 : template <class F>
731 : TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) & {
732 : using result = detail::invoke_result_t<F, T &>;
733 : static_assert(detail::is_optional<result>::value,
734 : "F must return an optional");
735 :
736 : return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt);
737 : }
738 :
739 : template <class F>
740 : TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &&> and_then(F &&f) && {
741 : using result = detail::invoke_result_t<F, T &&>;
742 : static_assert(detail::is_optional<result>::value,
743 : "F must return an optional");
744 :
745 : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
746 : : result(nullopt);
747 : }
748 :
749 : template <class F>
750 : constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const & {
751 : using result = detail::invoke_result_t<F, const T &>;
752 : static_assert(detail::is_optional<result>::value,
753 : "F must return an optional");
754 :
755 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
756 : : result(nullopt);
757 : }
758 :
759 : #ifndef TL_OPTIONAL_NO_CONSTRR
760 : template <class F>
761 : constexpr detail::invoke_result_t<F, const T &&> and_then(F &&f) const && {
762 : using result = detail::invoke_result_t<F, const T &&>;
763 : static_assert(detail::is_optional<result>::value,
764 : "F must return an optional");
765 :
766 : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
767 : : result(nullopt);
768 : }
769 : #endif
770 : #endif
771 :
772 : #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
773 : !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
774 : /// Carries out some operation on the stored object if there is one.
775 0 : template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) & {
776 0 : return optional_map_impl(*this, std::forward<F>(f));
777 : }
778 :
779 107137 : template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) && {
780 107137 : return optional_map_impl(std::move(*this), std::forward<F>(f));
781 : }
782 :
783 : template <class F> constexpr auto map(F &&f) const & {
784 : return optional_map_impl(*this, std::forward<F>(f));
785 : }
786 :
787 : template <class F> constexpr auto map(F &&f) const && {
788 : return optional_map_impl(std::move(*this), std::forward<F>(f));
789 : }
790 : #else
791 : /// Carries out some operation on the stored object if there is one.
792 : template <class F>
793 : TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional &>(),
794 : std::declval<F &&>()))
795 : map(F &&f) & {
796 : return optional_map_impl(*this, std::forward<F>(f));
797 : }
798 :
799 : template <class 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(std::move(*this), std::forward<F>(f));
804 : }
805 :
806 : template <class F>
807 : constexpr decltype(optional_map_impl(std::declval<const optional &>(),
808 : std::declval<F &&>()))
809 : map(F &&f) const & {
810 : return optional_map_impl(*this, std::forward<F>(f));
811 : }
812 :
813 : #ifndef TL_OPTIONAL_NO_CONSTRR
814 : template <class F>
815 : constexpr decltype(optional_map_impl(std::declval<const optional &&>(),
816 : std::declval<F &&>()))
817 : map(F &&f) const && {
818 : return optional_map_impl(std::move(*this), std::forward<F>(f));
819 : }
820 : #endif
821 : #endif
822 :
823 : #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
824 : !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
825 : /// Carries out some operation on the stored object if there is one.
826 : template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) & {
827 : return optional_map_impl(*this, std::forward<F>(f));
828 : }
829 :
830 : template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) && {
831 : return optional_map_impl(std::move(*this), std::forward<F>(f));
832 : }
833 :
834 : template <class F> constexpr auto transform(F&& f) const & {
835 : return optional_map_impl(*this, std::forward<F>(f));
836 : }
837 :
838 : template <class F> constexpr auto transform(F&& f) const && {
839 : return optional_map_impl(std::move(*this), std::forward<F>(f));
840 : }
841 : #else
842 : /// Carries out some operation on the stored object if there is one.
843 : template <class F>
844 : TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&>(),
845 : std::declval<F&&>()))
846 : transform(F&& f) & {
847 : return optional_map_impl(*this, std::forward<F>(f));
848 : }
849 :
850 : template <class 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(std::move(*this), std::forward<F>(f));
855 : }
856 :
857 : template <class F>
858 : constexpr decltype(optional_map_impl(std::declval<const optional&>(),
859 : std::declval<F&&>()))
860 : transform(F&& f) const & {
861 : return optional_map_impl(*this, std::forward<F>(f));
862 : }
863 :
864 : #ifndef TL_OPTIONAL_NO_CONSTRR
865 : template <class F>
866 : constexpr decltype(optional_map_impl(std::declval<const optional&&>(),
867 : std::declval<F&&>()))
868 : transform(F&& f) const && {
869 : return optional_map_impl(std::move(*this), std::forward<F>(f));
870 : }
871 : #endif
872 : #endif
873 :
874 : /// Calls `f` if the optional is empty
875 : template <class F, detail::enable_if_ret_void<F> * = nullptr>
876 : optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {
877 : if (has_value())
878 : return *this;
879 :
880 : std::forward<F>(f)();
881 : return nullopt;
882 : }
883 :
884 : template <class F, detail::disable_if_ret_void<F> * = nullptr>
885 : optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {
886 : return has_value() ? *this : std::forward<F>(f)();
887 : }
888 :
889 : template <class F, detail::enable_if_ret_void<F> * = nullptr>
890 : optional<T> or_else(F &&f) && {
891 : if (has_value())
892 : return std::move(*this);
893 :
894 : std::forward<F>(f)();
895 : return nullopt;
896 : }
897 :
898 : template <class F, detail::disable_if_ret_void<F> * = nullptr>
899 : optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) && {
900 : return has_value() ? std::move(*this) : std::forward<F>(f)();
901 : }
902 :
903 : template <class F, detail::enable_if_ret_void<F> * = nullptr>
904 : optional<T> or_else(F &&f) const & {
905 : if (has_value())
906 : return *this;
907 :
908 : std::forward<F>(f)();
909 : return nullopt;
910 : }
911 :
912 : template <class F, detail::disable_if_ret_void<F> * = nullptr>
913 : optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) const & {
914 : return has_value() ? *this : std::forward<F>(f)();
915 : }
916 :
917 : #ifndef TL_OPTIONAL_NO_CONSTRR
918 : template <class F, detail::enable_if_ret_void<F> * = nullptr>
919 : optional<T> or_else(F &&f) const && {
920 : if (has_value())
921 : return std::move(*this);
922 :
923 : std::forward<F>(f)();
924 : return nullopt;
925 : }
926 :
927 : template <class F, detail::disable_if_ret_void<F> * = nullptr>
928 : optional<T> or_else(F &&f) const && {
929 : return has_value() ? std::move(*this) : std::forward<F>(f)();
930 : }
931 : #endif
932 :
933 : /// Maps the stored value with `f` if there is one, otherwise returns `u`.
934 26 : template <class F, class U> U map_or(F &&f, U &&u) & {
935 21 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
936 5 : : std::forward<U>(u);
937 : }
938 :
939 : template <class F, class U> U map_or(F &&f, U &&u) && {
940 : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
941 : : std::forward<U>(u);
942 : }
943 :
944 215259 : template <class F, class U> U map_or(F &&f, U &&u) const & {
945 106001 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
946 215259 : : std::forward<U>(u);
947 109258 : }
948 :
949 : #ifndef TL_OPTIONAL_NO_CONSTRR
950 : template <class F, class U> U map_or(F &&f, U &&u) const && {
951 : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
952 : : std::forward<U>(u);
953 : }
954 : #endif
955 :
956 : /// Maps the stored value with `f` if there is one, otherwise calls
957 : /// `u` and returns the result.
958 : template <class F, class U>
959 : detail::invoke_result_t<U> map_or_else(F &&f, U &&u) & {
960 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
961 : : std::forward<U>(u)();
962 : }
963 :
964 : template <class F, class U>
965 : detail::invoke_result_t<U> map_or_else(F &&f, U &&u) && {
966 : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
967 : : std::forward<U>(u)();
968 : }
969 :
970 : template <class F, class U>
971 : detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const & {
972 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
973 : : std::forward<U>(u)();
974 : }
975 :
976 : #ifndef TL_OPTIONAL_NO_CONSTRR
977 : template <class F, class U>
978 : detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const && {
979 : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
980 : : std::forward<U>(u)();
981 : }
982 : #endif
983 :
984 : /// Returns `u` if `*this` has a value, otherwise an empty optional.
985 : template <class U>
986 : constexpr optional<typename std::decay<U>::type> conjunction(U &&u) const {
987 : using result = optional<detail::decay_t<U>>;
988 : return has_value() ? result{u} : result{nullopt};
989 : }
990 :
991 : /// Returns `rhs` if `*this` is empty, otherwise the current value.
992 : TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) & {
993 : return has_value() ? *this : rhs;
994 : }
995 :
996 : constexpr optional disjunction(const optional &rhs) const & {
997 : return has_value() ? *this : rhs;
998 : }
999 :
1000 : TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) && {
1001 : return has_value() ? std::move(*this) : rhs;
1002 : }
1003 :
1004 : #ifndef TL_OPTIONAL_NO_CONSTRR
1005 : constexpr optional disjunction(const optional &rhs) const && {
1006 : return has_value() ? std::move(*this) : rhs;
1007 : }
1008 : #endif
1009 :
1010 : TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) & {
1011 : return has_value() ? *this : std::move(rhs);
1012 : }
1013 :
1014 : constexpr optional disjunction(optional &&rhs) const & {
1015 : return has_value() ? *this : std::move(rhs);
1016 : }
1017 :
1018 : TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) && {
1019 : return has_value() ? std::move(*this) : std::move(rhs);
1020 : }
1021 :
1022 : #ifndef TL_OPTIONAL_NO_CONSTRR
1023 : constexpr optional disjunction(optional &&rhs) const && {
1024 : return has_value() ? std::move(*this) : std::move(rhs);
1025 : }
1026 : #endif
1027 :
1028 : /// Takes the value out of the optional, leaving it empty
1029 : optional take() {
1030 : optional ret = std::move(*this);
1031 : reset();
1032 : return ret;
1033 : }
1034 :
1035 : using value_type = T;
1036 :
1037 : /// Constructs an optional that does not contain a value.
1038 52015 : constexpr optional() noexcept = default;
1039 :
1040 190133 : constexpr optional(nullopt_t) noexcept {}
1041 :
1042 : /// Copy constructor
1043 : ///
1044 : /// If `rhs` contains a value, the stored value is direct-initialized with
1045 : /// it. Otherwise, the constructed optional is empty.
1046 4767674 : TL_OPTIONAL_11_CONSTEXPR optional(const optional &rhs) = default;
1047 :
1048 : /// Move constructor
1049 : ///
1050 : /// If `rhs` contains a value, the stored value is direct-initialized with
1051 : /// it. Otherwise, the constructed optional is empty.
1052 2533655 : TL_OPTIONAL_11_CONSTEXPR optional(optional &&rhs) = default;
1053 :
1054 : /// Constructs the stored value in-place using the given arguments.
1055 : template <class... Args>
1056 0 : constexpr explicit optional(
1057 : detail::enable_if_t<std::is_constructible<T, Args...>::value, in_place_t>,
1058 : Args &&... args)
1059 0 : : base(in_place, std::forward<Args>(args)...) {}
1060 :
1061 : template <class U, class... Args>
1062 : TL_OPTIONAL_11_CONSTEXPR explicit optional(
1063 : detail::enable_if_t<std::is_constructible<T, std::initializer_list<U> &,
1064 : Args &&...>::value,
1065 : in_place_t>,
1066 : std::initializer_list<U> il, Args &&... args) {
1067 : this->construct(il, std::forward<Args>(args)...);
1068 : }
1069 :
1070 : /// Constructs the stored value with `u`.
1071 : template <
1072 : class U = T,
1073 : detail::enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr,
1074 : detail::enable_forward_value<T, U> * = nullptr>
1075 9002198 : constexpr optional(U &&u) : base(in_place, std::forward<U>(u)) {}
1076 :
1077 : template <
1078 : class U = T,
1079 : detail::enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr,
1080 : detail::enable_forward_value<T, U> * = nullptr>
1081 : constexpr explicit optional(U &&u) : base(in_place, std::forward<U>(u)) {}
1082 :
1083 : /// Converting copy constructor.
1084 : template <
1085 : class U, detail::enable_from_other<T, U, const U &> * = nullptr,
1086 : detail::enable_if_t<std::is_convertible<const U &, T>::value> * = nullptr>
1087 12730 : optional(const optional<U> &rhs) {
1088 12730 : if (rhs.has_value()) {
1089 1 : this->construct(*rhs);
1090 : }
1091 12730 : }
1092 :
1093 : template <class U, detail::enable_from_other<T, U, const U &> * = nullptr,
1094 : detail::enable_if_t<!std::is_convertible<const U &, T>::value> * =
1095 : nullptr>
1096 : explicit optional(const optional<U> &rhs) {
1097 : if (rhs.has_value()) {
1098 : this->construct(*rhs);
1099 : }
1100 : }
1101 :
1102 : /// Converting move constructor.
1103 : template <
1104 : class U, detail::enable_from_other<T, U, U &&> * = nullptr,
1105 : detail::enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr>
1106 6498 : optional(optional<U> &&rhs) {
1107 6498 : if (rhs.has_value()) {
1108 6441 : this->construct(std::move(*rhs));
1109 : }
1110 6498 : }
1111 :
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>
1115 : explicit optional(optional<U> &&rhs) {
1116 : if (rhs.has_value()) {
1117 : this->construct(std::move(*rhs));
1118 : }
1119 : }
1120 :
1121 : /// Destroys the stored value if there is one.
1122 8411226 : ~optional() = default;
1123 :
1124 : /// Assignment to empty.
1125 : ///
1126 : /// Destroys the current value if there is one.
1127 4034 : optional &operator=(nullopt_t) noexcept {
1128 4034 : if (has_value()) {
1129 0 : this->m_value.~T();
1130 0 : this->m_has_value = false;
1131 : }
1132 :
1133 : return *this;
1134 : }
1135 :
1136 : /// Copy assignment.
1137 : ///
1138 : /// Copies the value from `rhs` if there is one. Otherwise resets the stored
1139 : /// value in `*this`.
1140 25394 : optional &operator=(const optional &rhs) = default;
1141 :
1142 : /// Move assignment.
1143 : ///
1144 : /// Moves the value from `rhs` if there is one. Otherwise resets the stored
1145 : /// value in `*this`.
1146 135986 : optional &operator=(optional &&rhs) = default;
1147 :
1148 : /// Assigns the stored value from `u`, destroying the old value if there was
1149 : /// one.
1150 : template <class U = T, detail::enable_assign_forward<T, U> * = nullptr>
1151 165391 : optional &operator=(U &&u) {
1152 165391 : if (has_value()) {
1153 32 : this->m_value = std::forward<U>(u);
1154 : } else {
1155 165360 : this->construct(std::forward<U>(u));
1156 : }
1157 :
1158 139028 : return *this;
1159 : }
1160 :
1161 : /// Converting copy assignment operator.
1162 : ///
1163 : /// Copies the value from `rhs` if there is one. Otherwise resets the stored
1164 : /// value in `*this`.
1165 : template <class U,
1166 : detail::enable_assign_from_other<T, U, const U &> * = nullptr>
1167 : optional &operator=(const optional<U> &rhs) {
1168 : if (has_value()) {
1169 : if (rhs.has_value()) {
1170 : this->m_value = *rhs;
1171 : } else {
1172 : this->hard_reset();
1173 : }
1174 : }
1175 :
1176 : else if (rhs.has_value()) {
1177 : this->construct(*rhs);
1178 : }
1179 :
1180 : return *this;
1181 : }
1182 :
1183 : // TODO check exception guarantee
1184 : /// Converting move assignment operator.
1185 : ///
1186 : /// Moves the value from `rhs` if there is one. Otherwise resets the stored
1187 : /// value in `*this`.
1188 : template <class U, detail::enable_assign_from_other<T, U, U> * = nullptr>
1189 : optional &operator=(optional<U> &&rhs) {
1190 : if (has_value()) {
1191 : if (rhs.has_value()) {
1192 : this->m_value = std::move(*rhs);
1193 : } else {
1194 : this->hard_reset();
1195 : }
1196 : }
1197 :
1198 : else if (rhs.has_value()) {
1199 : this->construct(std::move(*rhs));
1200 : }
1201 :
1202 : return *this;
1203 : }
1204 :
1205 : /// Constructs the value in-place, destroying the current one if there is
1206 : /// one.
1207 : template <class... Args> T &emplace(Args &&... args) {
1208 : static_assert(std::is_constructible<T, Args &&...>::value,
1209 : "T must be constructible with Args");
1210 :
1211 : *this = nullopt;
1212 : this->construct(std::forward<Args>(args)...);
1213 : return value();
1214 : }
1215 :
1216 : template <class U, class... Args>
1217 : detail::enable_if_t<
1218 : std::is_constructible<T, std::initializer_list<U> &, Args &&...>::value,
1219 : T &>
1220 : emplace(std::initializer_list<U> il, Args &&... args) {
1221 : *this = nullopt;
1222 : this->construct(il, std::forward<Args>(args)...);
1223 : return value();
1224 : }
1225 :
1226 : /// Swaps this optional with the other.
1227 : ///
1228 : /// If neither optionals have a value, nothing happens.
1229 : /// If both have a value, the values are swapped.
1230 : /// If one has a value, it is moved to the other and the movee is left
1231 : /// valueless.
1232 : void
1233 : swap(optional &rhs) noexcept(std::is_nothrow_move_constructible<T>::value
1234 : &&detail::is_nothrow_swappable<T>::value) {
1235 : using std::swap;
1236 : if (has_value()) {
1237 : if (rhs.has_value()) {
1238 : swap(**this, *rhs);
1239 : } else {
1240 : new (std::addressof(rhs.m_value)) T(std::move(this->m_value));
1241 : this->m_value.T::~T();
1242 : }
1243 : } else if (rhs.has_value()) {
1244 : new (std::addressof(this->m_value)) T(std::move(rhs.m_value));
1245 : rhs.m_value.T::~T();
1246 : }
1247 : swap(this->m_has_value, rhs.m_has_value);
1248 : }
1249 :
1250 : /// Returns a pointer to the stored value
1251 96211 : constexpr const T *operator->() const {
1252 : // constexpr function must only contain a return statement in C++11
1253 : #ifdef TL_OPTIONAL_CXX14
1254 : // undefined behavior if we don't have a value
1255 0 : rust_assert(has_value ());
1256 : #endif
1257 :
1258 96211 : return std::addressof(this->m_value);
1259 : }
1260 :
1261 587072 : TL_OPTIONAL_11_CONSTEXPR T *operator->() {
1262 : // constexpr function must only contain a return statement in C++11
1263 : #ifdef TL_OPTIONAL_CXX14
1264 : // undefined behavior if we don't have a value
1265 0 : rust_assert(has_value ());
1266 : #endif
1267 :
1268 587072 : return std::addressof(this->m_value);
1269 : }
1270 :
1271 : /// Returns the stored value
1272 5494940 : TL_OPTIONAL_11_CONSTEXPR T &operator*() &
1273 : {
1274 : // constexpr function must only contain a return statement in C++11
1275 : #ifdef TL_OPTIONAL_CXX14
1276 : // undefined behavior if we don't have a value
1277 0 : rust_assert(has_value ());
1278 : #endif
1279 :
1280 5494940 : return this->m_value;
1281 : }
1282 :
1283 219708 : constexpr const T &operator*() const &
1284 : {
1285 : // constexpr function must only contain a return statement in C++11
1286 : #ifdef TL_OPTIONAL_CXX14
1287 : // undefined behavior if we don't have a value
1288 0 : rust_assert(has_value ());
1289 : #endif
1290 :
1291 219708 : return this->m_value;
1292 : }
1293 :
1294 118246 : TL_OPTIONAL_11_CONSTEXPR T &&operator*() &&
1295 : {
1296 : // constexpr function must only contain a return statement in C++11
1297 : #ifdef TL_OPTIONAL_CXX14
1298 : // undefined behavior if we don't have a value
1299 0 : rust_assert(has_value ());
1300 : #endif
1301 :
1302 118246 : return std::move(this->m_value);
1303 : }
1304 :
1305 : #ifndef TL_OPTIONAL_NO_CONSTRR
1306 : constexpr const T &&operator*() const && { return std::move(this->m_value); }
1307 : #endif
1308 :
1309 : /// Returns whether or not the optional has a value
1310 14108083 : constexpr bool has_value() const noexcept { return this->m_has_value; }
1311 :
1312 6534294 : constexpr explicit operator bool() const noexcept {
1313 6419573 : return this->m_has_value;
1314 : }
1315 :
1316 : /// Returns the contained value if there is one, otherwise throws bad_optional_access
1317 6609183 : TL_OPTIONAL_11_CONSTEXPR T &value() & {
1318 6609183 : if (has_value())
1319 6609183 : return this->m_value;
1320 :
1321 0 : gcc_unreachable();
1322 : }
1323 171544 : TL_OPTIONAL_11_CONSTEXPR const T &value() const & {
1324 171544 : if (has_value())
1325 171544 : return this->m_value;
1326 :
1327 0 : gcc_unreachable();
1328 : }
1329 26558 : TL_OPTIONAL_11_CONSTEXPR T &&value() && {
1330 26558 : if (has_value())
1331 26558 : return std::move(this->m_value);
1332 :
1333 0 : gcc_unreachable();
1334 : }
1335 :
1336 : #ifndef TL_OPTIONAL_NO_CONSTRR
1337 : TL_OPTIONAL_11_CONSTEXPR const T &&value() const && {
1338 : if (has_value())
1339 : return std::move(this->m_value);
1340 :
1341 : gcc_unreachable();
1342 : }
1343 : #endif
1344 :
1345 : /// Returns the stored value if there is one, otherwise returns `u`
1346 : template <class U> constexpr T value_or(U &&u) const & {
1347 : static_assert(std::is_copy_constructible<T>::value &&
1348 : std::is_convertible<U &&, T>::value,
1349 : "T must be copy constructible and convertible from U");
1350 : return has_value() ? **this : static_cast<T>(std::forward<U>(u));
1351 : }
1352 :
1353 374 : template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && {
1354 : static_assert(std::is_move_constructible<T>::value &&
1355 : std::is_convertible<U &&, T>::value,
1356 : "T must be move constructible and convertible from U");
1357 374 : return has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(u));
1358 : }
1359 :
1360 : /// Destroys the stored value if one exists, making the optional empty
1361 : void reset() noexcept {
1362 : if (has_value()) {
1363 : this->m_value.~T();
1364 : this->m_has_value = false;
1365 : }
1366 : }
1367 : };
1368 :
1369 : /// Compares two optional objects
1370 : template <class T, class U>
1371 3897 : inline constexpr bool operator==(const optional<T> &lhs,
1372 : const optional<U> &rhs) {
1373 3897 : return lhs.has_value() == rhs.has_value() &&
1374 3897 : (!lhs.has_value() || *lhs == *rhs);
1375 : }
1376 : template <class T, class U>
1377 : inline constexpr bool operator!=(const optional<T> &lhs,
1378 : const optional<U> &rhs) {
1379 : return lhs.has_value() != rhs.has_value() ||
1380 : (lhs.has_value() && *lhs != *rhs);
1381 : }
1382 : template <class T, class U>
1383 : inline constexpr bool operator<(const optional<T> &lhs,
1384 : const optional<U> &rhs) {
1385 : return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs);
1386 : }
1387 : template <class T, class U>
1388 : inline constexpr bool operator>(const optional<T> &lhs,
1389 : const optional<U> &rhs) {
1390 : return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs);
1391 : }
1392 : template <class T, class U>
1393 : inline constexpr bool operator<=(const optional<T> &lhs,
1394 : const optional<U> &rhs) {
1395 : return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs);
1396 : }
1397 : template <class T, class U>
1398 : inline constexpr bool operator>=(const optional<T> &lhs,
1399 : const optional<U> &rhs) {
1400 : return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs);
1401 : }
1402 :
1403 : /// Compares an optional to a `nullopt`
1404 : template <class T>
1405 21191 : inline constexpr bool operator==(const optional<T> &lhs, nullopt_t) noexcept {
1406 21191 : return !lhs.has_value();
1407 : }
1408 : template <class T>
1409 : inline constexpr bool operator==(nullopt_t, const optional<T> &rhs) noexcept {
1410 : return !rhs.has_value();
1411 : }
1412 : template <class T>
1413 32 : inline constexpr bool operator!=(const optional<T> &lhs, nullopt_t) noexcept {
1414 32 : return lhs.has_value();
1415 : }
1416 : template <class T>
1417 : inline constexpr bool operator!=(nullopt_t, const optional<T> &rhs) noexcept {
1418 : return rhs.has_value();
1419 : }
1420 : template <class T>
1421 : inline constexpr bool operator<(const optional<T> &, nullopt_t) noexcept {
1422 : return false;
1423 : }
1424 : template <class T>
1425 : inline constexpr bool operator<(nullopt_t, const optional<T> &rhs) noexcept {
1426 : return rhs.has_value();
1427 : }
1428 : template <class T>
1429 : inline constexpr bool operator<=(const optional<T> &lhs, nullopt_t) noexcept {
1430 : return !lhs.has_value();
1431 : }
1432 : template <class T>
1433 : inline constexpr bool operator<=(nullopt_t, const optional<T> &) noexcept {
1434 : return true;
1435 : }
1436 : template <class T>
1437 : inline constexpr bool operator>(const optional<T> &lhs, nullopt_t) noexcept {
1438 : return lhs.has_value();
1439 : }
1440 : template <class T>
1441 : inline constexpr bool operator>(nullopt_t, const optional<T> &) noexcept {
1442 : return false;
1443 : }
1444 : template <class T>
1445 : inline constexpr bool operator>=(const optional<T> &, nullopt_t) noexcept {
1446 : return true;
1447 : }
1448 : template <class T>
1449 : inline constexpr bool operator>=(nullopt_t, const optional<T> &rhs) noexcept {
1450 : return !rhs.has_value();
1451 : }
1452 :
1453 : /// Compares the optional with a value.
1454 : template <class T, class U>
1455 62591 : inline constexpr bool operator==(const optional<T> &lhs, const U &rhs) {
1456 62591 : return lhs.has_value() ? *lhs == rhs : false;
1457 : }
1458 : template <class T, class U>
1459 : inline constexpr bool operator==(const U &lhs, const optional<T> &rhs) {
1460 : return rhs.has_value() ? lhs == *rhs : false;
1461 : }
1462 : template <class T, class U>
1463 22 : inline constexpr bool operator!=(const optional<T> &lhs, const U &rhs) {
1464 22 : return lhs.has_value() ? *lhs != rhs : true;
1465 : }
1466 : template <class T, class U>
1467 : inline constexpr bool operator!=(const U &lhs, const optional<T> &rhs) {
1468 : return rhs.has_value() ? lhs != *rhs : true;
1469 : }
1470 : template <class T, class U>
1471 : inline constexpr bool operator<(const optional<T> &lhs, const U &rhs) {
1472 : return lhs.has_value() ? *lhs < rhs : true;
1473 : }
1474 : template <class T, class U>
1475 : inline constexpr bool operator<(const U &lhs, const optional<T> &rhs) {
1476 : return rhs.has_value() ? lhs < *rhs : false;
1477 : }
1478 : template <class T, class U>
1479 : inline constexpr bool operator<=(const optional<T> &lhs, const U &rhs) {
1480 : return lhs.has_value() ? *lhs <= rhs : true;
1481 : }
1482 : template <class T, class U>
1483 : inline constexpr bool operator<=(const U &lhs, const optional<T> &rhs) {
1484 : return rhs.has_value() ? lhs <= *rhs : false;
1485 : }
1486 : template <class T, class U>
1487 : inline constexpr bool operator>(const optional<T> &lhs, const U &rhs) {
1488 : return lhs.has_value() ? *lhs > rhs : false;
1489 : }
1490 : template <class T, class U>
1491 : inline constexpr bool operator>(const U &lhs, const optional<T> &rhs) {
1492 : return rhs.has_value() ? lhs > *rhs : true;
1493 : }
1494 : template <class T, class U>
1495 : inline constexpr bool operator>=(const optional<T> &lhs, const U &rhs) {
1496 : return lhs.has_value() ? *lhs >= rhs : false;
1497 : }
1498 : template <class T, class U>
1499 : inline constexpr bool operator>=(const U &lhs, const optional<T> &rhs) {
1500 : return rhs.has_value() ? lhs >= *rhs : true;
1501 : }
1502 :
1503 : template <class T,
1504 : detail::enable_if_t<std::is_move_constructible<T>::value> * = nullptr,
1505 : detail::enable_if_t<detail::is_swappable<T>::value> * = nullptr>
1506 : void swap(optional<T> &lhs,
1507 : optional<T> &rhs) noexcept(noexcept(lhs.swap(rhs))) {
1508 : return lhs.swap(rhs);
1509 : }
1510 :
1511 : namespace detail {
1512 : struct i_am_secret {};
1513 : } // namespace detail
1514 :
1515 : template <class T = detail::i_am_secret, class U,
1516 : class Ret =
1517 : detail::conditional_t<std::is_same<T, detail::i_am_secret>::value,
1518 : detail::decay_t<U>, T>>
1519 : inline constexpr optional<Ret> make_optional(U &&v) {
1520 : return optional<Ret>(std::forward<U>(v));
1521 : }
1522 :
1523 : template <class T, class... Args>
1524 0 : inline constexpr optional<T> make_optional(Args &&... args) {
1525 0 : return optional<T>(in_place, std::forward<Args>(args)...);
1526 : }
1527 : template <class T, class U, class... Args>
1528 : inline constexpr optional<T> make_optional(std::initializer_list<U> il,
1529 : Args &&... args) {
1530 : return optional<T>(in_place, il, std::forward<Args>(args)...);
1531 : }
1532 :
1533 : #if __cplusplus >= 201703L
1534 : template <class T> optional(T)->optional<T>;
1535 : #endif
1536 :
1537 : /// \exclude
1538 : namespace detail {
1539 : #ifdef TL_OPTIONAL_CXX14
1540 : template <class Opt, class F,
1541 : class Ret = decltype(detail::invoke(std::declval<F>(),
1542 : *std::declval<Opt>())),
1543 : detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
1544 13335 : constexpr auto optional_map_impl(Opt &&opt, F &&f) {
1545 13335 : return opt.has_value()
1546 16440 : ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))
1547 13335 : : optional<Ret>(nullopt);
1548 : }
1549 :
1550 : template <class Opt, class F,
1551 : class Ret = decltype(detail::invoke(std::declval<F>(),
1552 : *std::declval<Opt>())),
1553 : detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
1554 95151 : auto optional_map_impl(Opt &&opt, F &&f) {
1555 95151 : if (opt.has_value()) {
1556 94103 : detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
1557 94103 : return make_optional(monostate{});
1558 : }
1559 :
1560 1048 : return optional<monostate>(nullopt);
1561 : }
1562 : #else
1563 : template <class Opt, class F,
1564 : class Ret = decltype(detail::invoke(std::declval<F>(),
1565 : *std::declval<Opt>())),
1566 : detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
1567 :
1568 : constexpr auto optional_map_impl(Opt &&opt, F &&f) -> optional<Ret> {
1569 : return opt.has_value()
1570 : ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))
1571 : : optional<Ret>(nullopt);
1572 : }
1573 :
1574 : template <class Opt, class F,
1575 : class Ret = decltype(detail::invoke(std::declval<F>(),
1576 : *std::declval<Opt>())),
1577 : detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
1578 :
1579 : auto optional_map_impl(Opt &&opt, F &&f) -> optional<monostate> {
1580 : if (opt.has_value()) {
1581 : detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
1582 : return monostate{};
1583 : }
1584 :
1585 : return nullopt;
1586 : }
1587 : #endif
1588 : } // namespace detail
1589 :
1590 : /// Specialization for when `T` is a reference. `optional<T&>` acts similarly
1591 : /// to a `T*`, but provides more operations and shows intent more clearly.
1592 : template <class T> class optional<T &> {
1593 : public:
1594 : // The different versions for C++14 and 11 are needed because deduced return
1595 : // types are not SFINAE-safe. This provides better support for things like
1596 : // generic lambdas. C.f.
1597 : // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html
1598 : #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
1599 : !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
1600 :
1601 : /// Carries out some operation which returns an optional on the stored
1602 : /// object if there is one.
1603 : template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) & {
1604 : using result = detail::invoke_result_t<F, T &>;
1605 : static_assert(detail::is_optional<result>::value,
1606 : "F must return an optional");
1607 :
1608 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1609 : : result(nullopt);
1610 : }
1611 :
1612 23703 : template <class F> TL_OPTIONAL_11_CONSTEXPR auto 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 23703 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1618 23703 : : result(nullopt);
1619 : }
1620 :
1621 : template <class F> constexpr auto and_then(F &&f) const & {
1622 : using result = detail::invoke_result_t<F, const T &>;
1623 : static_assert(detail::is_optional<result>::value,
1624 : "F must return an optional");
1625 :
1626 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1627 : : result(nullopt);
1628 : }
1629 :
1630 : #ifndef TL_OPTIONAL_NO_CONSTRR
1631 : template <class F> constexpr auto and_then(F &&f) const && {
1632 : using result = detail::invoke_result_t<F, const T &>;
1633 : static_assert(detail::is_optional<result>::value,
1634 : "F must return an optional");
1635 :
1636 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1637 : : result(nullopt);
1638 : }
1639 : #endif
1640 : #else
1641 : /// Carries out some operation which returns an optional on the stored
1642 : /// object if there is one.
1643 : template <class F>
1644 : TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) & {
1645 : using result = detail::invoke_result_t<F, T &>;
1646 : static_assert(detail::is_optional<result>::value,
1647 : "F must return an optional");
1648 :
1649 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1650 : : result(nullopt);
1651 : }
1652 :
1653 : template <class F>
1654 : TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) && {
1655 : using result = detail::invoke_result_t<F, T &>;
1656 : static_assert(detail::is_optional<result>::value,
1657 : "F must return an optional");
1658 :
1659 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1660 : : result(nullopt);
1661 : }
1662 :
1663 : template <class F>
1664 : constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const & {
1665 : using result = detail::invoke_result_t<F, const T &>;
1666 : static_assert(detail::is_optional<result>::value,
1667 : "F must return an optional");
1668 :
1669 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1670 : : result(nullopt);
1671 : }
1672 :
1673 : #ifndef TL_OPTIONAL_NO_CONSTRR
1674 : template <class F>
1675 : constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const && {
1676 : using result = detail::invoke_result_t<F, const T &>;
1677 : static_assert(detail::is_optional<result>::value,
1678 : "F must return an optional");
1679 :
1680 : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
1681 : : result(nullopt);
1682 : }
1683 : #endif
1684 : #endif
1685 :
1686 : #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
1687 : !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
1688 : /// Carries out some operation on the stored object if there is one.
1689 : template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) & {
1690 : return detail::optional_map_impl(*this, std::forward<F>(f));
1691 : }
1692 :
1693 1349 : template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) && {
1694 1349 : return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1695 : }
1696 :
1697 : template <class F> constexpr auto map(F &&f) const & {
1698 : return detail::optional_map_impl(*this, std::forward<F>(f));
1699 : }
1700 :
1701 : template <class F> constexpr auto map(F &&f) const && {
1702 : return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1703 : }
1704 : #else
1705 : /// Carries out some operation on the stored object if there is one.
1706 : template <class F>
1707 : TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional &>(),
1708 : std::declval<F &&>()))
1709 : map(F &&f) & {
1710 : return detail::optional_map_impl(*this, std::forward<F>(f));
1711 : }
1712 :
1713 : template <class F>
1714 : TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional &&>(),
1715 : std::declval<F &&>()))
1716 : map(F &&f) && {
1717 : return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1718 : }
1719 :
1720 : template <class F>
1721 : constexpr decltype(detail::optional_map_impl(std::declval<const optional &>(),
1722 : std::declval<F &&>()))
1723 : map(F &&f) const & {
1724 : return detail::optional_map_impl(*this, std::forward<F>(f));
1725 : }
1726 :
1727 : #ifndef TL_OPTIONAL_NO_CONSTRR
1728 : template <class F>
1729 : constexpr decltype(detail::optional_map_impl(std::declval<const optional &&>(),
1730 : std::declval<F &&>()))
1731 : map(F &&f) const && {
1732 : return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1733 : }
1734 : #endif
1735 : #endif
1736 :
1737 : #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
1738 : !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
1739 : /// Carries out some operation on the stored object if there is one.
1740 : template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) & {
1741 : return detail::optional_map_impl(*this, std::forward<F>(f));
1742 : }
1743 :
1744 : template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) && {
1745 : return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1746 : }
1747 :
1748 : template <class F> constexpr auto transform(F&& f) const & {
1749 : return detail::optional_map_impl(*this, std::forward<F>(f));
1750 : }
1751 :
1752 : template <class F> constexpr auto transform(F&& f) const && {
1753 : return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1754 : }
1755 : #else
1756 : /// Carries out some operation on the stored object if there is one.
1757 : template <class F>
1758 : TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&>(),
1759 : std::declval<F&&>()))
1760 : transform(F&& f) & {
1761 : return detail::optional_map_impl(*this, std::forward<F>(f));
1762 : }
1763 :
1764 : /// \group map
1765 : /// \synopsis template <class F> auto transform(F &&f) &&;
1766 : template <class F>
1767 : TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&&>(),
1768 : std::declval<F&&>()))
1769 : transform(F&& f) && {
1770 : return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1771 : }
1772 :
1773 : template <class F>
1774 : constexpr decltype(detail::optional_map_impl(std::declval<const optional&>(),
1775 : std::declval<F&&>()))
1776 : transform(F&& f) const & {
1777 : return detail::optional_map_impl(*this, std::forward<F>(f));
1778 : }
1779 :
1780 : #ifndef TL_OPTIONAL_NO_CONSTRR
1781 : template <class F>
1782 : constexpr decltype(detail::optional_map_impl(std::declval<const optional&&>(),
1783 : std::declval<F&&>()))
1784 : transform(F&& f) const && {
1785 : return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1786 : }
1787 : #endif
1788 : #endif
1789 :
1790 : /// Calls `f` if the optional is empty
1791 : template <class F, detail::enable_if_ret_void<F> * = nullptr>
1792 : optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {
1793 : if (has_value())
1794 : return *this;
1795 :
1796 : std::forward<F>(f)();
1797 : return nullopt;
1798 : }
1799 :
1800 : template <class F, detail::disable_if_ret_void<F> * = nullptr>
1801 : optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {
1802 : return has_value() ? *this : std::forward<F>(f)();
1803 : }
1804 :
1805 : template <class F, detail::enable_if_ret_void<F> * = nullptr>
1806 : optional<T> or_else(F &&f) && {
1807 : if (has_value())
1808 : return std::move(*this);
1809 :
1810 : std::forward<F>(f)();
1811 : return nullopt;
1812 : }
1813 :
1814 : template <class F, detail::disable_if_ret_void<F> * = nullptr>
1815 : optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) && {
1816 : return has_value() ? std::move(*this) : std::forward<F>(f)();
1817 : }
1818 :
1819 : template <class F, detail::enable_if_ret_void<F> * = nullptr>
1820 : optional<T> or_else(F &&f) const & {
1821 : if (has_value())
1822 : return *this;
1823 :
1824 : std::forward<F>(f)();
1825 : return nullopt;
1826 : }
1827 :
1828 : template <class F, detail::disable_if_ret_void<F> * = nullptr>
1829 : optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) const & {
1830 : return has_value() ? *this : std::forward<F>(f)();
1831 : }
1832 :
1833 : #ifndef TL_OPTIONAL_NO_CONSTRR
1834 : template <class F, detail::enable_if_ret_void<F> * = nullptr>
1835 : optional<T> or_else(F &&f) const && {
1836 : if (has_value())
1837 : return std::move(*this);
1838 :
1839 : std::forward<F>(f)();
1840 : return nullopt;
1841 : }
1842 :
1843 : template <class F, detail::disable_if_ret_void<F> * = nullptr>
1844 : optional<T> or_else(F &&f) const && {
1845 : return has_value() ? std::move(*this) : std::forward<F>(f)();
1846 : }
1847 : #endif
1848 :
1849 : /// Maps the stored value with `f` if there is one, otherwise returns `u`
1850 : template <class F, class U> U map_or(F &&f, U &&u) & {
1851 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1852 : : std::forward<U>(u);
1853 : }
1854 :
1855 : template <class F, class U> U map_or(F &&f, U &&u) && {
1856 : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
1857 : : std::forward<U>(u);
1858 : }
1859 :
1860 : template <class F, class U> U map_or(F &&f, U &&u) const & {
1861 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1862 : : std::forward<U>(u);
1863 : }
1864 :
1865 : #ifndef TL_OPTIONAL_NO_CONSTRR
1866 : template <class F, class U> U map_or(F &&f, U &&u) const && {
1867 : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
1868 : : std::forward<U>(u);
1869 : }
1870 : #endif
1871 :
1872 : /// Maps the stored value with `f` if there is one, otherwise calls
1873 : /// `u` and returns the result.
1874 : template <class F, class U>
1875 : detail::invoke_result_t<U> map_or_else(F &&f, U &&u) & {
1876 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1877 : : std::forward<U>(u)();
1878 : }
1879 :
1880 : template <class F, class U>
1881 : detail::invoke_result_t<U> map_or_else(F &&f, U &&u) && {
1882 : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
1883 : : std::forward<U>(u)();
1884 : }
1885 :
1886 : template <class F, class U>
1887 : detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const & {
1888 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1889 : : std::forward<U>(u)();
1890 : }
1891 :
1892 : #ifndef TL_OPTIONAL_NO_CONSTRR
1893 : template <class F, class U>
1894 : detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const && {
1895 : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
1896 : : std::forward<U>(u)();
1897 : }
1898 : #endif
1899 :
1900 : /// Returns `u` if `*this` has a value, otherwise an empty optional.
1901 : template <class U>
1902 : constexpr optional<typename std::decay<U>::type> conjunction(U &&u) const {
1903 : using result = optional<detail::decay_t<U>>;
1904 : return has_value() ? result{u} : result{nullopt};
1905 : }
1906 :
1907 : /// Returns `rhs` if `*this` is empty, otherwise the current value.
1908 : TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) & {
1909 : return has_value() ? *this : rhs;
1910 : }
1911 :
1912 : constexpr optional disjunction(const optional &rhs) const & {
1913 : return has_value() ? *this : rhs;
1914 : }
1915 :
1916 : TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) && {
1917 : return has_value() ? std::move(*this) : rhs;
1918 : }
1919 :
1920 : #ifndef TL_OPTIONAL_NO_CONSTRR
1921 : constexpr optional disjunction(const optional &rhs) const && {
1922 : return has_value() ? std::move(*this) : rhs;
1923 : }
1924 : #endif
1925 :
1926 : TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) & {
1927 : return has_value() ? *this : std::move(rhs);
1928 : }
1929 :
1930 : constexpr optional disjunction(optional &&rhs) const & {
1931 : return has_value() ? *this : std::move(rhs);
1932 : }
1933 :
1934 : TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) && {
1935 : return has_value() ? std::move(*this) : std::move(rhs);
1936 : }
1937 :
1938 : #ifndef TL_OPTIONAL_NO_CONSTRR
1939 : constexpr optional disjunction(optional &&rhs) const && {
1940 : return has_value() ? std::move(*this) : std::move(rhs);
1941 : }
1942 : #endif
1943 :
1944 : /// Takes the value out of the optional, leaving it empty
1945 : optional take() {
1946 : optional ret = std::move(*this);
1947 : reset();
1948 : return ret;
1949 : }
1950 :
1951 : using value_type = T &;
1952 :
1953 : /// Constructs an optional that does not contain a value.
1954 40590 : constexpr optional() noexcept : m_value(nullptr) {}
1955 :
1956 : constexpr optional(nullopt_t) noexcept : m_value(nullptr) {}
1957 :
1958 : /// Copy constructor
1959 : ///
1960 : /// If `rhs` contains a value, the stored value is direct-initialized with
1961 : /// it. Otherwise, the constructed optional is empty.
1962 : TL_OPTIONAL_11_CONSTEXPR optional(const optional &rhs) noexcept = default;
1963 :
1964 : /// Move constructor
1965 : ///
1966 : /// If `rhs` contains a value, the stored value is direct-initialized with
1967 : /// it. Otherwise, the constructed optional is empty.
1968 : TL_OPTIONAL_11_CONSTEXPR optional(optional &&rhs) = default;
1969 :
1970 : /// Constructs the stored value with `u`.
1971 : template <class U = T,
1972 : detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>
1973 : * = nullptr>
1974 1776712 : constexpr optional(U &&u) noexcept : m_value(std::addressof(u)) {
1975 : static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue");
1976 53 : }
1977 :
1978 : template <class U>
1979 : constexpr explicit optional(const optional<U> &rhs) noexcept : optional(*rhs) {}
1980 :
1981 : /// No-op
1982 : ~optional() = default;
1983 :
1984 : /// Assignment to empty.
1985 : ///
1986 : /// Destroys the current value if there is one.
1987 : optional &operator=(nullopt_t) noexcept {
1988 : m_value = nullptr;
1989 : return *this;
1990 : }
1991 :
1992 : /// Copy assignment.
1993 : ///
1994 : /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
1995 : /// resets the stored value in `*this`.
1996 : optional &operator=(const optional &rhs) = default;
1997 :
1998 : /// Rebinds this optional to `u`.
1999 : template <class U = T,
2000 : detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>
2001 : * = nullptr>
2002 2800 : optional &operator=(U &&u) {
2003 : static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue");
2004 2800 : m_value = std::addressof(u);
2005 0 : return *this;
2006 : }
2007 :
2008 : /// Converting copy assignment operator.
2009 : ///
2010 : /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
2011 : /// resets the stored value in `*this`.
2012 : template <class U> optional &operator=(const optional<U> &rhs) noexcept {
2013 : m_value = std::addressof(rhs.value());
2014 : return *this;
2015 : }
2016 :
2017 : /// Rebinds this optional to `u`.
2018 : template <class U = T,
2019 : detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>
2020 : * = nullptr>
2021 : optional &emplace(U &&u) noexcept {
2022 : return *this = std::forward<U>(u);
2023 : }
2024 :
2025 : void swap(optional &rhs) noexcept { std::swap(m_value, rhs.m_value); }
2026 :
2027 : /// Returns a pointer to the stored value
2028 0 : constexpr const T *operator->() const noexcept
2029 : {
2030 : // constexpr function must only contain a return statement in C++11
2031 : #ifdef TL_OPTIONAL_CXX14
2032 : // undefined behavior if we don't have a value
2033 0 : rust_assert(has_value ());
2034 : #endif
2035 :
2036 0 : return m_value;
2037 : }
2038 :
2039 22650 : TL_OPTIONAL_11_CONSTEXPR T *operator->() noexcept
2040 : {
2041 : // constexpr function must only contain a return statement in C++11
2042 : #ifdef TL_OPTIONAL_CXX14
2043 : // undefined behavior if we don't have a value
2044 0 : rust_assert(has_value ());
2045 : #endif
2046 :
2047 22650 : return m_value;
2048 : }
2049 :
2050 : /// Returns the stored value
2051 69018 : TL_OPTIONAL_11_CONSTEXPR T &operator*() noexcept {
2052 : // constexpr function must only contain a return statement in C++11
2053 : #ifdef TL_OPTIONAL_CXX14
2054 : // undefined behavior if we don't have a value
2055 0 : rust_assert(has_value ());
2056 : #endif
2057 :
2058 69018 : return *m_value;
2059 : }
2060 :
2061 0 : constexpr const T &operator*() const noexcept
2062 : {
2063 : // constexpr function must only contain a return statement in C++11
2064 : #ifdef TL_OPTIONAL_CXX14
2065 : // undefined behavior if we don't have a value
2066 0 : rust_assert(has_value ());
2067 : #endif
2068 :
2069 0 : return *m_value;
2070 : }
2071 :
2072 4225738 : constexpr bool has_value() const noexcept { return m_value != nullptr; }
2073 :
2074 160891 : constexpr explicit operator bool() const noexcept {
2075 160791 : return m_value != nullptr;
2076 : }
2077 :
2078 : /// Returns the contained value if there is one, otherwise throws bad_optional_access
2079 3381428 : TL_OPTIONAL_11_CONSTEXPR T &value() {
2080 3381428 : if (has_value())
2081 3381428 : return *m_value;
2082 :
2083 0 : gcc_unreachable();
2084 : }
2085 1 : TL_OPTIONAL_11_CONSTEXPR const T &value() const {
2086 1 : if (has_value())
2087 1 : return *m_value;
2088 :
2089 0 : gcc_unreachable();
2090 : }
2091 :
2092 : /// Returns the stored value if there is one, otherwise returns `u`
2093 0 : template <class U> constexpr T value_or(U &&u) const & noexcept {
2094 : static_assert(std::is_copy_constructible<T>::value &&
2095 : std::is_convertible<U &&, T>::value,
2096 : "T must be copy constructible and convertible from U");
2097 0 : return has_value() ? **this : static_cast<T>(std::forward<U>(u));
2098 : }
2099 :
2100 : /// \group value_or
2101 : template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && noexcept {
2102 : static_assert(std::is_move_constructible<T>::value &&
2103 : std::is_convertible<U &&, T>::value,
2104 : "T must be move constructible and convertible from U");
2105 : return has_value() ? **this : static_cast<T>(std::forward<U>(u));
2106 : }
2107 :
2108 : /// Destroys the stored value if one exists, making the optional empty
2109 : void reset() noexcept { m_value = nullptr; }
2110 :
2111 : private:
2112 : T *m_value;
2113 : };
2114 :
2115 :
2116 :
2117 : } // namespace tl
2118 :
2119 : namespace std {
2120 : // TODO SFINAE
2121 : template <class T> struct hash<tl::optional<T>> {
2122 54985 : ::std::size_t operator()(const tl::optional<T> &o) const {
2123 54985 : if (!o.has_value())
2124 : return 0;
2125 :
2126 54723 : return std::hash<tl::detail::remove_const_t<T>>()(*o);
2127 : }
2128 : };
2129 : } // namespace std
2130 :
2131 : #endif
|