Branch data 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 : 0 : 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 : 0 : 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 : 39 : 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 : 39 : 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 : 83146 : TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
357 : 73406 : : m_dummy(), m_has_value(false) {}
358 : :
359 : : template <class... U>
360 : 364013 : TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u)
361 : 566844 : : m_value(std::forward<U>(u)...), m_has_value(true) {}
362 : :
363 : 427738 : ~optional_storage_base() {
364 : 422988 : if (m_has_value) {
365 : 423842 : m_value.~T();
366 : : m_has_value = false;
367 : : }
368 : 217 : }
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 : 5873 : TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
382 : 5771 : : m_dummy(), m_has_value(false) {}
383 : :
384 : : template <class... U>
385 : 14197 : TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u)
386 : 7564 : : 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 : 943478 : template <class T> struct optional_operations_base : optional_storage_base<T> {
402 : 581103 : 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 : 77204 : template <class... Args> void construct(Args &&... args) {
410 : 78225 : new (std::addressof(this->m_value)) T(std::forward<Args>(args)...);
411 : 77204 : this->m_has_value = true;
412 : 76291 : }
413 : :
414 : : 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 : :
429 : 65013 : bool has_value() const { return this->m_has_value; }
430 : :
431 : 58568 : TL_OPTIONAL_11_CONSTEXPR T &get() & { return this->m_value; }
432 : 1748 : TL_OPTIONAL_11_CONSTEXPR const T &get() const & { return this->m_value; }
433 : : 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 : 5847 : struct optional_copy_base : optional_operations_base<T> {
443 : 8007 : 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 : 854676 : struct optional_copy_base<T, false> : optional_operations_base<T> {
449 : 573096 : using optional_operations_base<T>::optional_operations_base;
450 : :
451 : 79128 : optional_copy_base() = default;
452 : 4044 : optional_copy_base(const optional_copy_base &rhs)
453 : 4044 : : optional_operations_base<T>() {
454 : 4044 : if (rhs.has_value()) {
455 : 1748 : this->construct(rhs.get());
456 : : } else {
457 : : this->m_has_value = false;
458 : : }
459 : 4044 : }
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 : 5847 : struct optional_move_base : optional_copy_base<T> {
474 : 8007 : using optional_copy_base<T>::optional_copy_base;
475 : : };
476 : : #else
477 : : template <class T, bool = false> struct optional_move_base;
478 : : #endif
479 : 854676 : template <class T> struct optional_move_base<T, false> : optional_copy_base<T> {
480 : 573096 : using optional_copy_base<T>::optional_copy_base;
481 : :
482 : 18159 : optional_move_base() = default;
483 : 1812 : optional_move_base(const optional_move_base &rhs) = default;
484 : :
485 : 60969 : optional_move_base(optional_move_base &&rhs) noexcept(
486 : 60969 : std::is_nothrow_move_constructible<T>::value) {
487 : 60969 : if (rhs.has_value()) {
488 : 58568 : this->construct(std::move(rhs.get()));
489 : : } else {
490 : 1780 : this->m_has_value = false;
491 : : }
492 : 41465 : }
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 : 5847 : struct optional_copy_assign_base : optional_move_base<T> {
502 : 8007 : using optional_move_base<T>::optional_move_base;
503 : : };
504 : :
505 : : template <class T>
506 : 854676 : struct optional_copy_assign_base<T, false> : optional_move_base<T> {
507 : 573096 : using optional_move_base<T>::optional_move_base;
508 : :
509 : 18159 : optional_copy_assign_base() = default;
510 : 7344 : optional_copy_assign_base(const optional_copy_assign_base &rhs) = default;
511 : :
512 : 80473 : optional_copy_assign_base(optional_copy_assign_base &&rhs) = default;
513 : : 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 : 5847 : struct optional_move_assign_base : optional_copy_assign_base<T> {
531 : 8007 : 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 : 854676 : struct optional_move_assign_base<T, false> : optional_copy_assign_base<T> {
539 : 573096 : using optional_copy_assign_base<T>::optional_copy_assign_base;
540 : :
541 : 18159 : optional_move_assign_base() = default;
542 : 7344 : optional_move_assign_base(const optional_move_assign_base &rhs) = default;
543 : :
544 : 121938 : 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 &
550 : : 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 {};
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 : 12 : 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 : 10 : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
705 : 14 : : 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 : 0 : template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) && {
780 : 0 : return optional_map_impl(std::move(*this), std::forward<F>(f));
781 : : }
782 : :
783 : 0 : template <class F> constexpr auto map(F &&f) const & {
784 : 0 : 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 : 4 : template <class F, class U> U map_or(F &&f, U &&u) & {
935 : 5 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
936 : : : 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 : 19 : template <class F, class U> U map_or(F &&f, U &&u) const & {
945 : 38 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
946 : : : std::forward<U>(u);
947 : : }
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 : 8205 : constexpr optional() noexcept = default;
1039 : :
1040 : 12450 : 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 : 3300 : 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 : 70709 : 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 : : constexpr explicit optional(
1057 : : detail::enable_if_t<std::is_constructible<T, Args...>::value, in_place_t>,
1058 : : Args &&... args)
1059 : : : 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 : 378210 : 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 : : optional(const optional<U> &rhs) {
1088 : : if (rhs.has_value()) {
1089 : : this->construct(*rhs);
1090 : : }
1091 : : }
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 : 0 : optional(optional<U> &&rhs) {
1107 : 0 : if (rhs.has_value()) {
1108 : 0 : this->construct(std::move(*rhs));
1109 : : }
1110 : 0 : }
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 : 757276 : ~optional() = default;
1123 : :
1124 : : /// Assignment to empty.
1125 : : ///
1126 : : /// Destroys the current value if there is one.
1127 : 0 : optional &operator=(nullopt_t) noexcept {
1128 : 0 : 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 : : 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 : : 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 : 16915 : optional &operator=(U &&u) {
1152 : 16915 : if (has_value()) {
1153 : 51 : this->m_value = std::forward<U>(u);
1154 : : } else {
1155 : 16888 : this->construct(std::forward<U>(u));
1156 : : }
1157 : :
1158 : 16891 : 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 : : constexpr const T *operator->() const {
1252 : 0 : return std::addressof(this->m_value);
1253 : : }
1254 : :
1255 : : TL_OPTIONAL_11_CONSTEXPR T *operator->() {
1256 : 17125 : return std::addressof(this->m_value);
1257 : : }
1258 : :
1259 : : /// Returns the stored value
1260 : 48722 : TL_OPTIONAL_11_CONSTEXPR T &operator*() & { return this->m_value; }
1261 : :
1262 : 75378 : constexpr const T &operator*() const & { return this->m_value; }
1263 : :
1264 : 0 : TL_OPTIONAL_11_CONSTEXPR T &&operator*() && {
1265 : 0 : return std::move(this->m_value);
1266 : : }
1267 : :
1268 : : #ifndef TL_OPTIONAL_NO_CONSTRR
1269 : : constexpr const T &&operator*() const && { return std::move(this->m_value); }
1270 : : #endif
1271 : :
1272 : : /// Returns whether or not the optional has a value
1273 : 514742 : constexpr bool has_value() const noexcept { return this->m_has_value; }
1274 : :
1275 : 7055 : constexpr explicit operator bool() const noexcept {
1276 : 7055 : return this->m_has_value;
1277 : : }
1278 : :
1279 : : /// Returns the contained value if there is one, otherwise throws bad_optional_access
1280 : 366504 : TL_OPTIONAL_11_CONSTEXPR T &value() & {
1281 : 366504 : if (has_value())
1282 : 366504 : return this->m_value;
1283 : :
1284 : 0 : gcc_unreachable();
1285 : : }
1286 : 8014 : TL_OPTIONAL_11_CONSTEXPR const T &value() const & {
1287 : 8014 : if (has_value())
1288 : 8014 : return this->m_value;
1289 : :
1290 : 0 : gcc_unreachable();
1291 : : }
1292 : 14 : TL_OPTIONAL_11_CONSTEXPR T &&value() && {
1293 : 14 : if (has_value())
1294 : 14 : return std::move(this->m_value);
1295 : :
1296 : 0 : gcc_unreachable();
1297 : : }
1298 : :
1299 : : #ifndef TL_OPTIONAL_NO_CONSTRR
1300 : : TL_OPTIONAL_11_CONSTEXPR const T &&value() const && {
1301 : : if (has_value())
1302 : : return std::move(this->m_value);
1303 : :
1304 : : gcc_unreachable();
1305 : : }
1306 : : #endif
1307 : :
1308 : : /// Returns the stored value if there is one, otherwise returns `u`
1309 : : template <class U> constexpr T value_or(U &&u) const & {
1310 : : static_assert(std::is_copy_constructible<T>::value &&
1311 : : std::is_convertible<U &&, T>::value,
1312 : : "T must be copy constructible and convertible from U");
1313 : : return has_value() ? **this : static_cast<T>(std::forward<U>(u));
1314 : : }
1315 : :
1316 : 217 : template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && {
1317 : : static_assert(std::is_move_constructible<T>::value &&
1318 : : std::is_convertible<U &&, T>::value,
1319 : : "T must be move constructible and convertible from U");
1320 : 217 : return has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(u));
1321 : : }
1322 : :
1323 : : /// Destroys the stored value if one exists, making the optional empty
1324 : : void reset() noexcept {
1325 : : if (has_value()) {
1326 : : this->m_value.~T();
1327 : : this->m_has_value = false;
1328 : : }
1329 : : }
1330 : : }; // namespace tl
1331 : :
1332 : : /// Compares two optional objects
1333 : : template <class T, class U>
1334 : 936 : inline constexpr bool operator==(const optional<T> &lhs,
1335 : : const optional<U> &rhs) {
1336 : 936 : return lhs.has_value() == rhs.has_value() &&
1337 : 936 : (!lhs.has_value() || *lhs == *rhs);
1338 : : }
1339 : : template <class T, class U>
1340 : : inline constexpr bool operator!=(const optional<T> &lhs,
1341 : : const optional<U> &rhs) {
1342 : : return lhs.has_value() != rhs.has_value() ||
1343 : : (lhs.has_value() && *lhs != *rhs);
1344 : : }
1345 : : template <class T, class U>
1346 : : inline constexpr bool operator<(const optional<T> &lhs,
1347 : : const optional<U> &rhs) {
1348 : : return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs);
1349 : : }
1350 : : template <class T, class U>
1351 : : inline constexpr bool operator>(const optional<T> &lhs,
1352 : : const optional<U> &rhs) {
1353 : : return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs);
1354 : : }
1355 : : template <class T, class U>
1356 : : inline constexpr bool operator<=(const optional<T> &lhs,
1357 : : const optional<U> &rhs) {
1358 : : return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs);
1359 : : }
1360 : : template <class T, class U>
1361 : : inline constexpr bool operator>=(const optional<T> &lhs,
1362 : : const optional<U> &rhs) {
1363 : : return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs);
1364 : : }
1365 : :
1366 : : /// Compares an optional to a `nullopt`
1367 : : template <class T>
1368 : : inline constexpr bool operator==(const optional<T> &lhs, nullopt_t) noexcept {
1369 : : return !lhs.has_value();
1370 : : }
1371 : : template <class T>
1372 : : inline constexpr bool operator==(nullopt_t, const optional<T> &rhs) noexcept {
1373 : : return !rhs.has_value();
1374 : : }
1375 : : template <class T>
1376 : : inline constexpr bool operator!=(const optional<T> &lhs, nullopt_t) noexcept {
1377 : : return lhs.has_value();
1378 : : }
1379 : : template <class T>
1380 : : inline constexpr bool operator!=(nullopt_t, const optional<T> &rhs) noexcept {
1381 : : return rhs.has_value();
1382 : : }
1383 : : template <class T>
1384 : : inline constexpr bool operator<(const optional<T> &, nullopt_t) noexcept {
1385 : : return false;
1386 : : }
1387 : : template <class T>
1388 : : inline constexpr bool operator<(nullopt_t, const optional<T> &rhs) noexcept {
1389 : : return rhs.has_value();
1390 : : }
1391 : : template <class T>
1392 : : inline constexpr bool operator<=(const optional<T> &lhs, nullopt_t) noexcept {
1393 : : return !lhs.has_value();
1394 : : }
1395 : : template <class T>
1396 : : inline constexpr bool operator<=(nullopt_t, const optional<T> &) noexcept {
1397 : : return true;
1398 : : }
1399 : : template <class T>
1400 : : inline constexpr bool operator>(const optional<T> &lhs, nullopt_t) noexcept {
1401 : : return lhs.has_value();
1402 : : }
1403 : : template <class T>
1404 : : inline constexpr bool operator>(nullopt_t, const optional<T> &) noexcept {
1405 : : return false;
1406 : : }
1407 : : template <class T>
1408 : : inline constexpr bool operator>=(const optional<T> &, nullopt_t) noexcept {
1409 : : return true;
1410 : : }
1411 : : template <class T>
1412 : : inline constexpr bool operator>=(nullopt_t, const optional<T> &rhs) noexcept {
1413 : : return !rhs.has_value();
1414 : : }
1415 : :
1416 : : /// Compares the optional with a value.
1417 : : template <class T, class U>
1418 : 35910 : inline constexpr bool operator==(const optional<T> &lhs, const U &rhs) {
1419 : 35910 : return lhs.has_value() ? *lhs == rhs : false;
1420 : : }
1421 : : template <class T, class U>
1422 : : inline constexpr bool operator==(const U &lhs, const optional<T> &rhs) {
1423 : : return rhs.has_value() ? lhs == *rhs : false;
1424 : : }
1425 : : template <class T, class U>
1426 : : inline constexpr bool operator!=(const optional<T> &lhs, const U &rhs) {
1427 : : return lhs.has_value() ? *lhs != rhs : true;
1428 : : }
1429 : : template <class T, class U>
1430 : : inline constexpr bool operator!=(const U &lhs, const optional<T> &rhs) {
1431 : : return rhs.has_value() ? lhs != *rhs : true;
1432 : : }
1433 : : template <class T, class U>
1434 : : inline constexpr bool operator<(const optional<T> &lhs, const U &rhs) {
1435 : : return lhs.has_value() ? *lhs < rhs : true;
1436 : : }
1437 : : template <class T, class U>
1438 : : inline constexpr bool operator<(const U &lhs, const optional<T> &rhs) {
1439 : : return rhs.has_value() ? lhs < *rhs : false;
1440 : : }
1441 : : template <class T, class U>
1442 : : inline constexpr bool operator<=(const optional<T> &lhs, const U &rhs) {
1443 : : return lhs.has_value() ? *lhs <= rhs : true;
1444 : : }
1445 : : template <class T, class U>
1446 : : inline constexpr bool operator<=(const U &lhs, const optional<T> &rhs) {
1447 : : return rhs.has_value() ? lhs <= *rhs : false;
1448 : : }
1449 : : template <class T, class U>
1450 : : inline constexpr bool operator>(const optional<T> &lhs, const U &rhs) {
1451 : : return lhs.has_value() ? *lhs > rhs : false;
1452 : : }
1453 : : template <class T, class U>
1454 : : inline constexpr bool operator>(const U &lhs, const optional<T> &rhs) {
1455 : : return rhs.has_value() ? lhs > *rhs : true;
1456 : : }
1457 : : template <class T, class U>
1458 : : inline constexpr bool operator>=(const optional<T> &lhs, const U &rhs) {
1459 : : return lhs.has_value() ? *lhs >= rhs : false;
1460 : : }
1461 : : template <class T, class U>
1462 : : inline constexpr bool operator>=(const U &lhs, const optional<T> &rhs) {
1463 : : return rhs.has_value() ? lhs >= *rhs : true;
1464 : : }
1465 : :
1466 : : template <class T,
1467 : : detail::enable_if_t<std::is_move_constructible<T>::value> * = nullptr,
1468 : : detail::enable_if_t<detail::is_swappable<T>::value> * = nullptr>
1469 : : void swap(optional<T> &lhs,
1470 : : optional<T> &rhs) noexcept(noexcept(lhs.swap(rhs))) {
1471 : : return lhs.swap(rhs);
1472 : : }
1473 : :
1474 : : namespace detail {
1475 : : struct i_am_secret {};
1476 : : } // namespace detail
1477 : :
1478 : : template <class T = detail::i_am_secret, class U,
1479 : : class Ret =
1480 : : detail::conditional_t<std::is_same<T, detail::i_am_secret>::value,
1481 : : detail::decay_t<U>, T>>
1482 : : inline constexpr optional<Ret> make_optional(U &&v) {
1483 : : return optional<Ret>(std::forward<U>(v));
1484 : : }
1485 : :
1486 : : template <class T, class... Args>
1487 : : inline constexpr optional<T> make_optional(Args &&... args) {
1488 : : return optional<T>(in_place, std::forward<Args>(args)...);
1489 : : }
1490 : : template <class T, class U, class... Args>
1491 : : inline constexpr optional<T> make_optional(std::initializer_list<U> il,
1492 : : Args &&... args) {
1493 : : return optional<T>(in_place, il, std::forward<Args>(args)...);
1494 : : }
1495 : :
1496 : : #if __cplusplus >= 201703L
1497 : : template <class T> optional(T)->optional<T>;
1498 : : #endif
1499 : :
1500 : : /// \exclude
1501 : : namespace detail {
1502 : : #ifdef TL_OPTIONAL_CXX14
1503 : : template <class Opt, class F,
1504 : : class Ret = decltype(detail::invoke(std::declval<F>(),
1505 : : *std::declval<Opt>())),
1506 : : detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
1507 : 0 : constexpr auto optional_map_impl(Opt &&opt, F &&f) {
1508 : 0 : return opt.has_value()
1509 : 0 : ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))
1510 : 0 : : optional<Ret>(nullopt);
1511 : : }
1512 : :
1513 : : template <class Opt, class F,
1514 : : class Ret = decltype(detail::invoke(std::declval<F>(),
1515 : : *std::declval<Opt>())),
1516 : : detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
1517 : : auto optional_map_impl(Opt &&opt, F &&f) {
1518 : : if (opt.has_value()) {
1519 : : detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
1520 : : return make_optional(monostate{});
1521 : : }
1522 : :
1523 : : return optional<monostate>(nullopt);
1524 : : }
1525 : : #else
1526 : : template <class Opt, class F,
1527 : : class Ret = decltype(detail::invoke(std::declval<F>(),
1528 : : *std::declval<Opt>())),
1529 : : detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
1530 : :
1531 : : constexpr auto optional_map_impl(Opt &&opt, F &&f) -> optional<Ret> {
1532 : : return opt.has_value()
1533 : : ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))
1534 : : : optional<Ret>(nullopt);
1535 : : }
1536 : :
1537 : : template <class Opt, class F,
1538 : : class Ret = decltype(detail::invoke(std::declval<F>(),
1539 : : *std::declval<Opt>())),
1540 : : detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
1541 : :
1542 : : auto optional_map_impl(Opt &&opt, F &&f) -> optional<monostate> {
1543 : : if (opt.has_value()) {
1544 : : detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
1545 : : return monostate{};
1546 : : }
1547 : :
1548 : : return nullopt;
1549 : : }
1550 : : #endif
1551 : : } // namespace detail
1552 : :
1553 : : /// Specialization for when `T` is a reference. `optional<T&>` acts similarly
1554 : : /// to a `T*`, but provides more operations and shows intent more clearly.
1555 : : template <class T> class optional<T &> {
1556 : : public:
1557 : : // The different versions for C++14 and 11 are needed because deduced return
1558 : : // types are not SFINAE-safe. This provides better support for things like
1559 : : // generic lambdas. C.f.
1560 : : // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html
1561 : : #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
1562 : : !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
1563 : :
1564 : : /// Carries out some operation which returns an optional on the stored
1565 : : /// object if there is one.
1566 : : template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) & {
1567 : : using result = detail::invoke_result_t<F, T &>;
1568 : : static_assert(detail::is_optional<result>::value,
1569 : : "F must return an optional");
1570 : :
1571 : : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1572 : : : result(nullopt);
1573 : : }
1574 : :
1575 : 12 : template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) && {
1576 : : using result = detail::invoke_result_t<F, T &>;
1577 : : static_assert(detail::is_optional<result>::value,
1578 : : "F must return an optional");
1579 : :
1580 : 9 : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1581 : 3 : : result(nullopt);
1582 : : }
1583 : :
1584 : : template <class F> constexpr auto and_then(F &&f) const & {
1585 : : using result = detail::invoke_result_t<F, const T &>;
1586 : : static_assert(detail::is_optional<result>::value,
1587 : : "F must return an optional");
1588 : :
1589 : : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1590 : : : result(nullopt);
1591 : : }
1592 : :
1593 : : #ifndef TL_OPTIONAL_NO_CONSTRR
1594 : : template <class F> constexpr auto and_then(F &&f) const && {
1595 : : using result = detail::invoke_result_t<F, const T &>;
1596 : : static_assert(detail::is_optional<result>::value,
1597 : : "F must return an optional");
1598 : :
1599 : : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1600 : : : result(nullopt);
1601 : : }
1602 : : #endif
1603 : : #else
1604 : : /// Carries out some operation which returns an optional on the stored
1605 : : /// object if there is one.
1606 : : template <class F>
1607 : : TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) & {
1608 : : using result = detail::invoke_result_t<F, T &>;
1609 : : static_assert(detail::is_optional<result>::value,
1610 : : "F must return an optional");
1611 : :
1612 : : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1613 : : : result(nullopt);
1614 : : }
1615 : :
1616 : : template <class F>
1617 : : TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) && {
1618 : : using result = detail::invoke_result_t<F, T &>;
1619 : : static_assert(detail::is_optional<result>::value,
1620 : : "F must return an optional");
1621 : :
1622 : : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1623 : : : result(nullopt);
1624 : : }
1625 : :
1626 : : template <class F>
1627 : : constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const & {
1628 : : using result = detail::invoke_result_t<F, const T &>;
1629 : : static_assert(detail::is_optional<result>::value,
1630 : : "F must return an optional");
1631 : :
1632 : : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1633 : : : result(nullopt);
1634 : : }
1635 : :
1636 : : #ifndef TL_OPTIONAL_NO_CONSTRR
1637 : : template <class F>
1638 : : constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const && {
1639 : : using result = detail::invoke_result_t<F, const T &>;
1640 : : static_assert(detail::is_optional<result>::value,
1641 : : "F must return an optional");
1642 : :
1643 : : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
1644 : : : result(nullopt);
1645 : : }
1646 : : #endif
1647 : : #endif
1648 : :
1649 : : #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
1650 : : !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
1651 : : /// Carries out some operation on the stored object if there is one.
1652 : : template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) & {
1653 : : return detail::optional_map_impl(*this, std::forward<F>(f));
1654 : : }
1655 : :
1656 : : template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) && {
1657 : : return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1658 : : }
1659 : :
1660 : : template <class F> constexpr auto map(F &&f) const & {
1661 : : return detail::optional_map_impl(*this, std::forward<F>(f));
1662 : : }
1663 : :
1664 : : template <class F> constexpr auto map(F &&f) const && {
1665 : : return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1666 : : }
1667 : : #else
1668 : : /// Carries out some operation on the stored object if there is one.
1669 : : template <class F>
1670 : : TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional &>(),
1671 : : std::declval<F &&>()))
1672 : : map(F &&f) & {
1673 : : return detail::optional_map_impl(*this, std::forward<F>(f));
1674 : : }
1675 : :
1676 : : template <class F>
1677 : : TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional &&>(),
1678 : : std::declval<F &&>()))
1679 : : map(F &&f) && {
1680 : : return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1681 : : }
1682 : :
1683 : : template <class F>
1684 : : constexpr decltype(detail::optional_map_impl(std::declval<const optional &>(),
1685 : : std::declval<F &&>()))
1686 : : map(F &&f) const & {
1687 : : return detail::optional_map_impl(*this, std::forward<F>(f));
1688 : : }
1689 : :
1690 : : #ifndef TL_OPTIONAL_NO_CONSTRR
1691 : : template <class F>
1692 : : constexpr decltype(detail::optional_map_impl(std::declval<const optional &&>(),
1693 : : std::declval<F &&>()))
1694 : : map(F &&f) const && {
1695 : : return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1696 : : }
1697 : : #endif
1698 : : #endif
1699 : :
1700 : : #if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
1701 : : !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
1702 : : /// Carries out some operation on the stored object if there is one.
1703 : : template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) & {
1704 : : return detail::optional_map_impl(*this, std::forward<F>(f));
1705 : : }
1706 : :
1707 : : template <class F> TL_OPTIONAL_11_CONSTEXPR auto transform(F&& f) && {
1708 : : return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1709 : : }
1710 : :
1711 : : template <class F> constexpr auto transform(F&& f) const & {
1712 : : return detail::optional_map_impl(*this, std::forward<F>(f));
1713 : : }
1714 : :
1715 : : template <class F> constexpr auto transform(F&& f) const && {
1716 : : return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1717 : : }
1718 : : #else
1719 : : /// Carries out some operation on the stored object if there is one.
1720 : : template <class F>
1721 : : TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&>(),
1722 : : std::declval<F&&>()))
1723 : : transform(F&& f) & {
1724 : : return detail::optional_map_impl(*this, std::forward<F>(f));
1725 : : }
1726 : :
1727 : : /// \group map
1728 : : /// \synopsis template <class F> auto transform(F &&f) &&;
1729 : : template <class F>
1730 : : TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&&>(),
1731 : : std::declval<F&&>()))
1732 : : transform(F&& f) && {
1733 : : return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1734 : : }
1735 : :
1736 : : template <class F>
1737 : : constexpr decltype(detail::optional_map_impl(std::declval<const optional&>(),
1738 : : std::declval<F&&>()))
1739 : : transform(F&& f) const & {
1740 : : return detail::optional_map_impl(*this, std::forward<F>(f));
1741 : : }
1742 : :
1743 : : #ifndef TL_OPTIONAL_NO_CONSTRR
1744 : : template <class F>
1745 : : constexpr decltype(detail::optional_map_impl(std::declval<const optional&&>(),
1746 : : std::declval<F&&>()))
1747 : : transform(F&& f) const && {
1748 : : return detail::optional_map_impl(std::move(*this), std::forward<F>(f));
1749 : : }
1750 : : #endif
1751 : : #endif
1752 : :
1753 : : /// Calls `f` if the optional is empty
1754 : : template <class F, detail::enable_if_ret_void<F> * = nullptr>
1755 : : optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {
1756 : : if (has_value())
1757 : : return *this;
1758 : :
1759 : : std::forward<F>(f)();
1760 : : return nullopt;
1761 : : }
1762 : :
1763 : : template <class F, detail::disable_if_ret_void<F> * = nullptr>
1764 : : optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) & {
1765 : : return has_value() ? *this : std::forward<F>(f)();
1766 : : }
1767 : :
1768 : : template <class F, detail::enable_if_ret_void<F> * = nullptr>
1769 : : optional<T> or_else(F &&f) && {
1770 : : if (has_value())
1771 : : return std::move(*this);
1772 : :
1773 : : std::forward<F>(f)();
1774 : : return nullopt;
1775 : : }
1776 : :
1777 : : template <class F, detail::disable_if_ret_void<F> * = nullptr>
1778 : : optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) && {
1779 : : return has_value() ? std::move(*this) : std::forward<F>(f)();
1780 : : }
1781 : :
1782 : : template <class F, detail::enable_if_ret_void<F> * = nullptr>
1783 : : optional<T> or_else(F &&f) const & {
1784 : : if (has_value())
1785 : : return *this;
1786 : :
1787 : : std::forward<F>(f)();
1788 : : return nullopt;
1789 : : }
1790 : :
1791 : : template <class F, detail::disable_if_ret_void<F> * = nullptr>
1792 : : optional<T> TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) const & {
1793 : : return has_value() ? *this : std::forward<F>(f)();
1794 : : }
1795 : :
1796 : : #ifndef TL_OPTIONAL_NO_CONSTRR
1797 : : template <class F, detail::enable_if_ret_void<F> * = nullptr>
1798 : : optional<T> or_else(F &&f) const && {
1799 : : if (has_value())
1800 : : return std::move(*this);
1801 : :
1802 : : std::forward<F>(f)();
1803 : : return nullopt;
1804 : : }
1805 : :
1806 : : template <class F, detail::disable_if_ret_void<F> * = nullptr>
1807 : : optional<T> or_else(F &&f) const && {
1808 : : return has_value() ? std::move(*this) : std::forward<F>(f)();
1809 : : }
1810 : : #endif
1811 : :
1812 : : /// Maps the stored value with `f` if there is one, otherwise returns `u`
1813 : : template <class F, class U> U map_or(F &&f, U &&u) & {
1814 : : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1815 : : : std::forward<U>(u);
1816 : : }
1817 : :
1818 : : template <class F, class U> U map_or(F &&f, U &&u) && {
1819 : : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
1820 : : : std::forward<U>(u);
1821 : : }
1822 : :
1823 : : template <class F, class U> U map_or(F &&f, U &&u) const & {
1824 : : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1825 : : : std::forward<U>(u);
1826 : : }
1827 : :
1828 : : #ifndef TL_OPTIONAL_NO_CONSTRR
1829 : : template <class F, class U> U map_or(F &&f, U &&u) const && {
1830 : : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
1831 : : : std::forward<U>(u);
1832 : : }
1833 : : #endif
1834 : :
1835 : : /// Maps the stored value with `f` if there is one, otherwise calls
1836 : : /// `u` and returns the result.
1837 : : template <class F, class U>
1838 : : detail::invoke_result_t<U> map_or_else(F &&f, U &&u) & {
1839 : : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1840 : : : std::forward<U>(u)();
1841 : : }
1842 : :
1843 : : template <class F, class U>
1844 : : detail::invoke_result_t<U> map_or_else(F &&f, U &&u) && {
1845 : : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
1846 : : : std::forward<U>(u)();
1847 : : }
1848 : :
1849 : : template <class F, class U>
1850 : : detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const & {
1851 : : return has_value() ? detail::invoke(std::forward<F>(f), **this)
1852 : : : std::forward<U>(u)();
1853 : : }
1854 : :
1855 : : #ifndef TL_OPTIONAL_NO_CONSTRR
1856 : : template <class F, class U>
1857 : : detail::invoke_result_t<U> map_or_else(F &&f, U &&u) const && {
1858 : : return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
1859 : : : std::forward<U>(u)();
1860 : : }
1861 : : #endif
1862 : :
1863 : : /// Returns `u` if `*this` has a value, otherwise an empty optional.
1864 : : template <class U>
1865 : : constexpr optional<typename std::decay<U>::type> conjunction(U &&u) const {
1866 : : using result = optional<detail::decay_t<U>>;
1867 : : return has_value() ? result{u} : result{nullopt};
1868 : : }
1869 : :
1870 : : /// Returns `rhs` if `*this` is empty, otherwise the current value.
1871 : : TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) & {
1872 : : return has_value() ? *this : rhs;
1873 : : }
1874 : :
1875 : : constexpr optional disjunction(const optional &rhs) const & {
1876 : : return has_value() ? *this : rhs;
1877 : : }
1878 : :
1879 : : TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) && {
1880 : : return has_value() ? std::move(*this) : rhs;
1881 : : }
1882 : :
1883 : : #ifndef TL_OPTIONAL_NO_CONSTRR
1884 : : constexpr optional disjunction(const optional &rhs) const && {
1885 : : return has_value() ? std::move(*this) : rhs;
1886 : : }
1887 : : #endif
1888 : :
1889 : : TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) & {
1890 : : return has_value() ? *this : std::move(rhs);
1891 : : }
1892 : :
1893 : : constexpr optional disjunction(optional &&rhs) const & {
1894 : : return has_value() ? *this : std::move(rhs);
1895 : : }
1896 : :
1897 : : TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) && {
1898 : : return has_value() ? std::move(*this) : std::move(rhs);
1899 : : }
1900 : :
1901 : : #ifndef TL_OPTIONAL_NO_CONSTRR
1902 : : constexpr optional disjunction(optional &&rhs) const && {
1903 : : return has_value() ? std::move(*this) : std::move(rhs);
1904 : : }
1905 : : #endif
1906 : :
1907 : : /// Takes the value out of the optional, leaving it empty
1908 : : optional take() {
1909 : : optional ret = std::move(*this);
1910 : : reset();
1911 : : return ret;
1912 : : }
1913 : :
1914 : : using value_type = T &;
1915 : :
1916 : : /// Constructs an optional that does not contain a value.
1917 : 24720 : constexpr optional() noexcept : m_value(nullptr) {}
1918 : :
1919 : 126 : constexpr optional(nullopt_t) noexcept : m_value(nullptr) {}
1920 : :
1921 : : /// Copy constructor
1922 : : ///
1923 : : /// If `rhs` contains a value, the stored value is direct-initialized with
1924 : : /// it. Otherwise, the constructed optional is empty.
1925 : : TL_OPTIONAL_11_CONSTEXPR optional(const optional &rhs) noexcept = default;
1926 : :
1927 : : /// Move constructor
1928 : : ///
1929 : : /// If `rhs` contains a value, the stored value is direct-initialized with
1930 : : /// it. Otherwise, the constructed optional is empty.
1931 : : TL_OPTIONAL_11_CONSTEXPR optional(optional &&rhs) = default;
1932 : :
1933 : : /// Constructs the stored value with `u`.
1934 : : template <class U = T,
1935 : : detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>
1936 : : * = nullptr>
1937 : 5430 : constexpr optional(U &&u) noexcept : m_value(std::addressof(u)) {
1938 : : static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue");
1939 : 0 : }
1940 : :
1941 : : template <class U>
1942 : : constexpr explicit optional(const optional<U> &rhs) noexcept : optional(*rhs) {}
1943 : :
1944 : : /// No-op
1945 : : ~optional() = default;
1946 : :
1947 : : /// Assignment to empty.
1948 : : ///
1949 : : /// Destroys the current value if there is one.
1950 : : optional &operator=(nullopt_t) noexcept {
1951 : : m_value = nullptr;
1952 : : return *this;
1953 : : }
1954 : :
1955 : : /// Copy assignment.
1956 : : ///
1957 : : /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
1958 : : /// resets the stored value in `*this`.
1959 : : optional &operator=(const optional &rhs) = default;
1960 : :
1961 : : /// Rebinds this optional to `u`.
1962 : : template <class U = T,
1963 : : detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>
1964 : : * = nullptr>
1965 : 2284 : optional &operator=(U &&u) {
1966 : : static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue");
1967 : 2284 : m_value = std::addressof(u);
1968 : 19 : return *this;
1969 : : }
1970 : :
1971 : : /// Converting copy assignment operator.
1972 : : ///
1973 : : /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise
1974 : : /// resets the stored value in `*this`.
1975 : : template <class U> optional &operator=(const optional<U> &rhs) noexcept {
1976 : : m_value = std::addressof(rhs.value());
1977 : : return *this;
1978 : : }
1979 : :
1980 : : /// Rebinds this optional to `u`.
1981 : : template <class U = T,
1982 : : detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>
1983 : : * = nullptr>
1984 : : optional &emplace(U &&u) noexcept {
1985 : : return *this = std::forward<U>(u);
1986 : : }
1987 : :
1988 : : void swap(optional &rhs) noexcept { std::swap(m_value, rhs.m_value); }
1989 : :
1990 : : /// Returns a pointer to the stored value
1991 : : constexpr const T *operator->() const noexcept { return m_value; }
1992 : :
1993 : 2309 : TL_OPTIONAL_11_CONSTEXPR T *operator->() noexcept { return m_value; }
1994 : :
1995 : : /// Returns the stored value
1996 : 1 : TL_OPTIONAL_11_CONSTEXPR T &operator*() noexcept { return *m_value; }
1997 : :
1998 : : constexpr const T &operator*() const noexcept { return *m_value; }
1999 : :
2000 : 398744 : constexpr bool has_value() const noexcept { return m_value != nullptr; }
2001 : :
2002 : : constexpr explicit operator bool() const noexcept {
2003 : : return m_value != nullptr;
2004 : : }
2005 : :
2006 : : /// Returns the contained value if there is one, otherwise throws bad_optional_access
2007 : 3905 : TL_OPTIONAL_11_CONSTEXPR T &value() {
2008 : 3905 : if (has_value())
2009 : 3905 : return *m_value;
2010 : :
2011 : 0 : gcc_unreachable();
2012 : : }
2013 : : TL_OPTIONAL_11_CONSTEXPR const T &value() const {
2014 : : if (has_value())
2015 : : return *m_value;
2016 : :
2017 : : gcc_unreachable();
2018 : : }
2019 : :
2020 : : /// Returns the stored value if there is one, otherwise returns `u`
2021 : : template <class U> constexpr T value_or(U &&u) const & noexcept {
2022 : : static_assert(std::is_copy_constructible<T>::value &&
2023 : : std::is_convertible<U &&, T>::value,
2024 : : "T must be copy constructible and convertible from U");
2025 : : return has_value() ? **this : static_cast<T>(std::forward<U>(u));
2026 : : }
2027 : :
2028 : : /// \group value_or
2029 : : template <class U> TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && noexcept {
2030 : : static_assert(std::is_move_constructible<T>::value &&
2031 : : std::is_convertible<U &&, T>::value,
2032 : : "T must be move constructible and convertible from U");
2033 : : return has_value() ? **this : static_cast<T>(std::forward<U>(u));
2034 : : }
2035 : :
2036 : : /// Destroys the stored value if one exists, making the optional empty
2037 : : void reset() noexcept { m_value = nullptr; }
2038 : :
2039 : : private:
2040 : : T *m_value;
2041 : : }; // namespace tl
2042 : :
2043 : :
2044 : :
2045 : : } // namespace tl
2046 : :
2047 : : namespace std {
2048 : : // TODO SFINAE
2049 : : template <class T> struct hash<tl::optional<T>> {
2050 : 41658 : ::std::size_t operator()(const tl::optional<T> &o) const {
2051 : 41658 : if (!o.has_value())
2052 : : return 0;
2053 : :
2054 : 41472 : return std::hash<tl::detail::remove_const_t<T>>()(*o);
2055 : : }
2056 : : };
2057 : : } // namespace std
2058 : :
2059 : : #endif
|